Azsde Azsde - 2 months ago 17
Java Question

Kryonet chat POC timeout issue

So, i'm experimenting a little bit with the Kryonet library, and to start i've decided to develop a simple chat program that would allow to communicate from the client (the remote computer) to the server (local machine).

Everything seems to work, i'm able to receive messages from the client to my server.

But there's a big annoying issue : if the client doesn't send any packet (here the packets are text messages) for a certain time, he gets disconnected by the server saying that he timed out.

I'm struggling with this and I don't know how to fix this ...

Here are the sources of my programs ( except commented out

//all my imports
so as to avoid having tons of lines of import ... ) :

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 (server side)

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 (common to server and client)

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 (client side)

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");
}
}
}


Can someone tell me what i'm doing wrong ? I'd like to keep the connection between the client and the server alive even if the client has been idle for a long time.

Thank you in advance !

Answer

I did something very stupid.

Having this : mpacket.message = ChattyClient.scanner.nextLine(); makes my program wait for a input, thus, during this period, no keepAlive packet were sent to the server.