Java multithreaded server hangs
tejas238 opened this issue · comments
Hello,
I’m trying to develop a multithreaded server which continuously accepts connections and creates a new thread for each client socket. The client socket then receives Java object requests and sends Java object responses (object streaming).
As long as I only have a single connection I.e. one client socket thread and one server thread there is no problem — the client socket remains active responding to message requests— but as soon as I have 2 clients I.e. 2 client socket threads, after serving a few requests (4-5), the client socket hangs while writing out the response object at the ZerotierNative.zts_bsd_write() native call— I traced it to this call in the debugger. Opening another client thread does not help, the new thread also hangs whenever it needs to write out and I have to restart the application.
I wonder if I’m running into some socket related race condition because of not starting/closing a client socket correctly (I looked at the source and can see that there are locks being held and freed for each zts_bsd_write() -> lwip_write() call but could not make much sense of it)…
Looking for some general guidance on multithreading sockets patterns and if I’m overlooking something or if it could be a bug in the library?
This is for a POC at our startup— if it meets our needs we would be looking into a paid engagement.
Anything looking wrong here?
`
public class Server implements Runnable {
private String networkIdValue = "#";
private String ztIp;
private ZeroTierNode node;
private ZeroTierServerSocket listener;
public static List<ClientHandler> clients = new ArrayList<>();
private Integer port = 8999;
private void initializeServerSocket() throws IOException {
listener = new ZeroTierServerSocket(port);
//listener.setSoTimeout(5000);
while (true) {
ZeroTierSocket clientSocket = listener.accept();
System.out.println("Client connected: " + clientSocket.isConnected());
//clientSocket.setKeepAliveEnabled(false);
//clientSocket.setSoTimeout(10000);
System.out.println("Creating client handler");
ClientHandler clientHandler = new ClientHandler(clientSocket);
clients.add(clientHandler);
System.out.println("Staring client handler");
clientHandler.start();
System.out.println("Started client handler");
}
}
static class ClientHandler extends Thread {
private ZeroTierSocket conn;
private ObjectOutputStream objectOutputStream;
private ObjectInputStream objectInputStream;
public ClientHandler(ZeroTierSocket socket) {
this.conn = socket;
}
@Override
public void run() {
try {
HashMap<String,Object> map;
String json;
System.out.println("Getting socket streams");
ZeroTierOutputStream outputStream = conn.getOutputStream();
ZeroTierInputStream inputStream = conn.getInputStream();
System.out.println("Creating output socket object");
objectOutputStream = new ObjectOutputStream(outputStream);
System.out.println("Creating input socket object");
objectInputStream = new ObjectInputStream(inputStream);
while(true) {
System.out.println("waiting for obj");
map = (HashMap<String,Object>) objectInputStream.readObject();
System.out.println("Received: " + map.get("type"));
switch(map.get("type").toString()) {
case "DEVICE_REQUEST":
try {
json = MessageHandler.handleDeviceReq();
System.out.println("request" + json);
objectOutputStream.writeObject(json); //hangs here after opening 2nd socket after 4-5 message requests
System.out.println("flushed");
} catch (Exception ex) {
System.out.println("Exception in device req");
ex.printStackTrace();
json = MessageHandler.handleException("DEVICE_RESPONSE_EXCEPTION", ex);
objectOutputStream.writeObject(json);
}
break;
}
}
} catch (Exception ex) {
System.out.println("Exception in client socket");
ex.printStackTrace();
this.shutdown();
}
}
}
}`