My questions is more generic than the following scenario, though this covers everything needed. It is for Java and the correct practices of socket programming.
Scenario:
- One server with many clients. Usage of non-blocking I/O
- The server is a client to another server. Usage of blocking I/O
- Two cases for each: in one case all data fit inside the allocated bytebuffer, in the second case they do not fit (for one iteration only, not for the lifespan of the program).
All examples that I have found for a non-blocking I/O go something like this:
InetAddress host = InetAddress.getByName("localhost");
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(host, 1234));
serverSocketChannel.register(selector, SelectionKey. OP_ACCEPT);
while (true) {
if (selector.select() <= 0)
continue;
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()) {
key = (SelectionKey) iterator.next();
iterator.remove();
if (key.isAcceptable()) {
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
// Do something or do nothing
}
if (key.isReadable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
socketChannel.read(buffer);
// Something something dark side
if (result.length() <= 0) {
sc.close();
// Something else
}
}
}
Does the read
here reads all incoming data from that particular client and that particular request, if the buffer is large enough, or do I need to have it inside a while
loop? If the buffer is not large enough?
In case of a write
, do I also just do socketChannel.write(buffer)
and I am good to go (at least from the programs point of view)?
The doc here does not specify the case when all incoming data fit in the buffer. It also makes it a bit confusing when I have a blocking I/O:
It is guaranteed, however, that if a channel is in blocking mode and there is at least one byte remaining in the buffer then this method will block until at least one byte is read.
Does this mean that here (blocking I/O) I need to read
through a while
loop either way (most examples that I found does this)? What about a write
operation?
So, to sum it up, my question is, what is the proper way to read and write the data in my scenario, from the point of view of the middle server (client to the second server)?