javanionio2

How do you close a AsynchronousSocketChannel cleanly?


My server uses a AsynchronousServerSocketChannel that listens for client connections using a CompletionHandler. When a client connection is accepted, the AsynchronousSocketChannel is read, again using a CompletionHandler to receive the data with no timeout.

So far so good, my client connects, writes data that is read by the server, which is able to respond sending data back to the client via the same socket.

When my client terminates, it calls AsynchronousSocketChannel.close(), to close the socket. When this call is made the server is waiting to read data from the socket.

I had expected the call to AsynchronousSocketChannel.close() on the client to translate into a callback to CompletionHandler.completed with a read length of -1 on the server, indicating the socket had been closed, however the callback is to CompletionHandler.failed with the following exception:

java.io.IOException: The specified network name is no longer available.
  at sun.nio.ch.Iocp.translateErrorToIOException(Iocp.java:309)
  at sun.nio.ch.Iocp.access$700(Iocp.java:46)
  at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:399)
  at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  at java.lang.Thread.run(Thread.java:744)    

How should a client close a socket, so that it is not seen as an error on the server?


Solution

  • The documentation on close says that it causes AsynchronousCloseException or ClosedChannelException on the other side.

    To cause completed(-1) the client should call shutdownInput.

    However, I would treat AsynchronousCloseException and ClosedChannelException as normal shutdown, along with completed(-1).