Kryonet聊天POC超时问题



因此,我正在对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),最简单的解决方案是:

  1. 在每个发送方为您的消息策略配备aKeepAliveMsgINJECTOR,以便通过连接异步激发"静止"消息(是的,在您的应用程序级别,因此独立于底层传输保持活动)
  2. 在每个接收方实现一个IncomingMessageFILTER,以从[[aKeepAliveMSG]]]信令/控制有效负载中分离有用的聊天内容

这样做后,您可以根据自己的意愿或随着您的消息传递架构需求的增长,在这种琐碎的信令/控制层中添加更多的逻辑。

相关内容

  • 没有找到相关文章

最新更新