Hi folks!
I'm using a non-blocking java.nio.SocketChannel for high-performance multi-threaded client to server communication. Everythings works as intended, but when I shutdown my client application (which ultimately exits the sender thread), not all data is sent to the server.
This behaviour is due to the inability to check if the java.nio.SocketChannel has sent all bytes; there is no method like flush() to force the data to be sent over the wire or writeFinished() which could be polled until everything has been written.
Here is some pseudo code without synchronization and thread issues to clarify the problem:
The SocketChannel is created like this:
SocketChannel socketChannel = SocketChannel.open();
socketChannel.socket().setTcpNoDelay(true);
socketChannel.connect(new InetSocketAddress(serverHost, serverPort));
socketChannel.configureBlocking(false);
A java.nio.ByteBuffer is used to store events/messages asynchronously:
ByteBuffer buffer = new ByteBuffer;
ByteBuffer.allocateDirect(512*1024); // 512kb
When the buffer is full, I call buffer.flip() and send it repeatedly via socketChannel.write(buffer) until buffer.remaining() == 0.
When the client application exits, I made sure that buffer.remaining() == 0 but due to the very nature of NIO I can't make sure the data is actually sent over the wire. It only means that the native NIO buffer now contains the contents of ByteBuffer (or some parts of it).
Right now, I can only work around this problem by inserting a highly esotheric Thread.sleep(500) just before the client application exits and hope that the contents of the native nio.SocketChannel's bytebuffer (take a look at IOUtils) have been sent completely over the wire.
Question: How can i make sure that all data has been sent to the server before client application has been exited?
Kind regards,
weznme