views:

55

answers:

4

Basically I want to create a rock solid server.

while (keepRunning.get()) {
    try {
        Socket clientSocket = serverSocket.accept();

        ... spawn a new thread to handle the client ...
    } catch (IOException e) {
        e.printStackTrace();
        // NOW WHAT?
    }
}

In the IOException block, what to do? Is the Server socket at fault so it need to be recreated? For example wait a few seconds and then

serverSocket = ServerSocketFactory.getDefault().createServerSocket(MY_PORT);

However if the server socket is still OK, then it is a pity to close it and kill all previously accepted connections that are still communicating.

EDIT: After some answers, here my attempt to deal with the IOException. Would the implementation be guaranteeing keeping the server up and only re-create server socket when only necessary?

while (keepRunning.get()) {
    try {
        Socket clientSocket = serverSocket.accept();

        ... spawn a new thread to handle the client ...
        bindExceptionCounter = 0;
    } catch (IOException e) {
        e.printStackTrace();

        recreateServerSocket();
    }
}

private void recreateServerSocket() {
    while (keepRunning) {
        try {
            logger.info("Try to re-create Server Socket");
            ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(RateTableServer.RATE_EVENT_SERVER_PORT);

            // No exception thrown, then use the new socket.
            serverSocket = socket;
            break;
        } catch (BindException e) {
            logger.info("BindException indicates that the server socket is still good.", e);
            bindExceptionCounter++;

            if (bindExceptionCounter < 5) {
                break;
            }
        } catch (IOException e) {
            logger.warn("Problem to re-create Server Socket", e);
            e.printStackTrace();

            try {
                Thread.sleep(30000);
            } catch (InterruptedException ie) {
                logger.warn(ie);
            }
        }
    }
}    
+1  A: 

Make sure you differentiate between different IOExceptions you might receive. Is it an exception on creating a connection? Is it an exception once a connection has already been established?

The only code you gave is for accept()ing. Generally speaking, an IOException usually means an error on any layer on the physical network.

Probably the best fallback behavior you can implement is to wait for a certain time quantum, and then try to reconnect. Assume you most possibly will not be able to reconnect, since you have lost network connection for more than a temporary period. Make sure you handle this gracefully. As @mdma mentioned, this must be supported by your clients as well.

Yuval A
reconnect - You mean create the server socket again?
s5804
If you lost the socket then yes...
Yuval A
+1  A: 

If in doubt, you could try re-creating the server socket, using the same port. If the socket has been closed, then the creation will succeed and you can continue processing new connections. The old connections are gone, but that's outside of your control since the socket was closed. If the socket was not closed, then creating a new instance will fail since the port is still in use, which you can just ignore - i.e. don't replace the current server socket reference.

In general, clients should also assume that connections will be broken and that reconnection is necessary. In other words, it's not just the server that has to be robust - clients should also anticipate connection errors and reconnect.

mdma
If creating a new server socket, which fails with BindException - would this mean that it is 100% sure that the old server socket is fully OK?
s5804
I can't say "yes" for sure, but in general I would assume that. I would also use a defensive strategy. E.g. if you get X number of failures calling accept, then you might consider the server socket somehow broken, and choose to close the server socket.
mdma
A: 

You can get an IOException on an accept() if the server socket is closed (by you) or you run out of resources, e.g. file handles. Either way, there is not much you can do about it. If the serverSocket is closed (you can test for this) you probably had a good reason to do this. If you run out of resources, you will either have to increase your resource limit, which requires a restart of your application, or you have a resource leak.

Peter Lawrey
How to test if the socket is closed? I thought that serversocket.isClosed() always return false, because the higher layer don't get notified by the lower levels. Is this correct?
s5804
+1  A: 

However if the server socket is still OK, then it is a pity to close it and kill all previously accepted connections that are still communicating.

Please note that closing the server socket will NOT close previously accepted connections. As soon as a connection has been accepted it lives a separate, joyful life at a different port.

volley