因此,我正在对Kryonet库进行一些实验,首先我决定开发一个简单的聊天程序,允许从客户端(远程计算机)到服务器(本地机器)进行通信。
一切似乎都正常,我可以从客户端接收到服务器的消息。
但有一个大的令人讨厌的问题:如果客户端在一定时间内没有发送任何数据包(这里的数据包是短信),他就会被服务器断开连接,说他超时了。
我正在为此而挣扎,我不知道如何解决这个问题。。。
以下是我的程序的来源(除了注释掉//all my imports
,以避免有大量的导入行…):
ChattyServer.java
package com.azsde.Chatty;
//all my imports
public class ChattyServer {
//Mes objets
private Server server;
private ArrayList <Clients> clientsList;
//Mes méthodes
//Constructeur
public ChattyServer() throws IOException
{
clientsList = new ArrayList <Clients>();
server = new Server();
registerPackets();
server.addListener(new NetworkListener(clientsList));
server.bind(101);
server.start();
// Open a window to provide an easy way to stop the server.
JFrame frame = new JFrame("Chatty Server");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosed (WindowEvent evt)
{
server.stop();
}
});
frame.getContentPane().add(new JLabel("Close to stop the server."));
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.SOUTH);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//Packet3Order order = new Packet3Order();
//order.start = true;
//server.getConnections()[0].sendTCP(order);
listClients();
}
});
panel.add(btnNewButton);
frame.setSize(320, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void registerPackets()
{
Kryo kryo = server.getKryo();
kryo.register(Packet0ConnectionRequest.class);
kryo.register(Packet1RequestResponse.class);
kryo.register(Packet2Message.class);
kryo.register(Packet3Order.class);
}
private void listClients()
{
for (int i = 0 ; i < clientsList.size() ; i ++)
{
if (!clientsList.isEmpty())
{
System.out.println(clientsList.get(i).getUsername());
System.out.println(clientsList.get(i).getIpAdress());
}
}
}
public static void main (String[] args) {
try {
new ChattyServer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.set(Log.LEVEL_DEBUG);
}
}
NetworkListener.java(服务器端)
package com.azsde.Chatty;
//All my imports
public class ChattyServer {
//Mes objets
private Server server;
private ArrayList <Clients> clientsList;
//Mes méthodes
//Constructeur
public ChattyServer() throws IOException
{
clientsList = new ArrayList <Clients>();
server = new Server();
registerPackets();
server.addListener(new NetworkListener(clientsList));
server.bind(101);
server.start();
// Open a window to provide an easy way to stop the server.
JFrame frame = new JFrame("Chatty Server");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosed (WindowEvent evt)
{
server.stop();
}
});
frame.getContentPane().add(new JLabel("Close to stop the server."));
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.SOUTH);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
listClients();
}
});
panel.add(btnNewButton);
frame.setSize(320, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void registerPackets()
{
Kryo kryo = server.getKryo();
kryo.register(Packet0ConnectionRequest.class);
kryo.register(Packet1RequestResponse.class);
kryo.register(Packet2Message.class);
kryo.register(Packet3Order.class);
}
private void listClients()
{
for (int i = 0 ; i < clientsList.size() ; i ++)
{
if (!clientsList.isEmpty())
{
System.out.println(clientsList.get(i).getUsername());
System.out.println(clientsList.get(i).getIpAdress());
}
}
}
public static void main (String[] args)
{
try {
new ChattyServer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.set(Log.LEVEL_DEBUG);
}
}
Packet.java(服务器和客户端通用)
package com.azsde.Chatty;
public class Packet {
public static class Packet0ConnectionRequest {String username;}
public static class Packet1RequestResponse {Boolean accepted = false;}
public static class Packet2Message {String message;}
public static class Packet3Order {Boolean start = false;}
}
ChattyClient.java
package com.azsde.Chatty;
//My imports
public class ChattyClient {
public Client client;
public static Scanner scanner;
public ChattyClient()
{
scanner = new Scanner(System.in);
client = new Client();
register();
NetworkListener nl = new NetworkListener();
nl.init(client);
client.addListener(nl);
client.start();
client.setKeepAliveTCP(50);
try
{
client.connect(50000, "127.0.0.1", 101);
}
catch (IOException e)
{
e.printStackTrace();
client.close();
}
}
private void register()
{
Kryo kryo = client.getKryo();
kryo.register(Packet0ConnectionRequest.class);
kryo.register(Packet1RequestResponse.class);
kryo.register(Packet2Message.class);
kryo.register(Packet3Order.class);
}
public static void main (String[] args)
{
new ChattyClient();
Log.set(Log.LEVEL_DEBUG);
}
}
NetworkListener.java(客户端)
package com.azsde.Chatty;
//My imports
public class NetworkListener extends Listener
{
private Client client;
public void init(Client client)
{
this.client = client;
}
public void connected(Connection arg0)
{
Packet0ConnectionRequest conRequest = new Packet0ConnectionRequest();
conRequest.username = System.getProperty("user.name");
Log.info("[CLIENT] You have connected");
client.sendTCP(conRequest);
}
public void disconnected(Connection arg0)
{
Log.info("[CLIENT] You have disconnected.");
}
public void received(Connection c, Object o)
{
if ( o instanceof Packet1RequestResponse)
{
Log.info("I got a response");
if (((Packet1RequestResponse) o).accepted)
{
Log.info("[CLIENT] You have connected.");
while(true)
{
if (ChattyClient.scanner.hasNext())
{
Log.info("Enter your message : ");
Packet2Message mpacket = new Packet2Message();
mpacket.message = ChattyClient.scanner.nextLine();
client.sendTCP(mpacket);
}
}
}
else
{
Log.info("[CLIENT] Connection failed.");
c.close();
}
}
if ( o instanceof Packet3Order)
{
Log.info("I got an order");
if (((Packet3Order) o).start) Log.info("Start");
else Log.info("Stop");
}
}
}
有人能告诉我我做错了什么吗?即使客户端空闲很长时间,我也希望保持客户端和服务器之间的连接。
提前谢谢!
我做了一件非常愚蠢的事。
有了这个:mpacket.message = ChattyClient.scanner.nextLine();
使我的程序等待输入,因此,在此期间,没有向服务器发送keepAlive数据包。
消息系统可以根据需要设置/处理连接一次,也可以设置/维护连接并向通道提供流控制对象(也称为KeepAlive消息)(也可能包含有关连接或客户端/服务器端状态等的遥测详细信息)。
因此,根据您的任务定义(保持连接)和(避免空闲状态下的T/O),最简单的解决方案是:
- 在每个发送方为您的消息策略配备aKeepAliveMsgINJECTOR,以便通过连接异步激发"静止"消息(是的,在您的应用程序级别,因此独立于底层传输保持活动)
- 在每个接收方实现一个IncomingMessageFILTER,以从[[aKeepAliveMSG]]]信令/控制有效负载中分离有用的聊天内容
这样做后,您可以根据自己的意愿或随着您的消息传递架构需求的增长,在这种琐碎的信令/控制层中添加更多的逻辑。