Kryonet聊天POC超时问题

时间:2014-09-28 21:41:28

标签: java timeout kryonet

所以,我正在尝试一下Kryonet库,并开始我决定开发一个简单的聊天程序,允许从客户端(远程计算机)到服务器进行通信(本地机器)。

一切似乎都有效,我能够从客户端接收消息到我的服务器。

但是有一个很烦人的问题:如果客户端在一段时间内没有发送任何数据包(这里的数据包是文本消息),他会被服务器断开连接,说他超时了。 / p>

我正在努力解决这个问题而且我不知道如何解决这个问题......

以下是我的程序的来源(除了//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");
    }
}
}

有人可以告诉我我做错了什么吗?即使客户端已经闲置了很长时间,我也希望客户端和服务器之间保持连接。

提前谢谢!

2 个答案:

答案 0 :(得分:0)

消息传递系统可根据需要设置/部署连接一次,或者设置/维护连接并使用流控制对象(也称为KeepAlive消息)提供通道(其中还可能包含有关连接或客户端/服务器端状态的遥测详细信息)等)。

因此,根据您的任务定义(保持连接)和(避免空闲状态下的T / O),最简单的解决方案是:

  1. 装备您的消息传递策略,在每个发送方都使用 aKeepAliveMsgINJECTOR 通过连接异步触发“仍然在这里”的消息(是的,在您的应用程序级别,因此独立于潜在的运输保持活着)
  2. 每个接收方的
  3. 实施 anIncomingMessageFILTER ,以便从[[[[[[[[[[[[[[[[[[[[[[[[<

    完成此操作后,您可以根据自己的意愿或在消息传递体系结构需求增长时,将更多逻辑添加到此类简单的信令/控制层中。

答案 1 :(得分:0)

我做了一些非常愚蠢的事。

拥有:mpacket.message = ChattyClient.scanner.nextLine();使我的程序等待输入,因此,在此期间,没有keepAlive数据包被发送到服务器。