zerotier / libzt

Encrypted P2P sockets over ZeroTier

Home Page:https://zerotier.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

}`