Java NIO - keeping up a bi-directional link
in
Programming Questions
•
2 years ago
Some time ago I posted here a question on how to make my existing game java-nio-multiplayer enabled since I am totally new to network programming.. Alright, since then I have made everything going. And while the project is still in development, all is working fine. However, there is one more question on Java NIO that i can't answer myself: how to make the channel simultaneously bi-directional?
Let me explain what I mean. Java NIO philosophy is based on SelectionKeys that have some interesting ops set. For example, there are SelectionKey.OP_READ and SelectionKey.OP_WRITE interests. When one of these is set, the channel is considered operable in one of these ways (read/write). Thus the interest has to be changed accordingly to what am I going to do. The decision is based on fact that something is needed to be written to the channel. But there is no inherit way to determine if it is so. So, when finished sending all info, the sender, sends a NetworkReady message, and turns to OP_READ. All data on the receiver is read and processed. The last message that comes from sender is the NetworkReady. Upon receiving this message, the receiver changes his state to OP_WRITE. All this means that now the sender and receiver have swapped their roles. Let me illustrate:
A - OP_ACCEPT
W - OP_WRITE
R - OP_READ
HS - Handshake
D - Useful data
N - NetwrokReady
s - server
c - client
- 1. s(A) server awaits connections
- 2. s(A) <- c client connects
- 3. s(W) -HS+N-> с(R) after successful connection, client becomes R, server becomes W.
- 4. s(R) <-HS+N- с(W) client responds with handshake
- 5. s(W) -D+N--> c(R) starting to send useful data
- 6. s(R) <--D+N- c(W) this way
- 7. s(W) -D+N--> c(R) that way
- 8. s(R) <--D+N- c(W) this way
- 9. s(W) -D+N--> c(R) that way
- .. s(R) <--D+N- c(W) this way
- .... and so on.... and so on...
When a client needs to send something to the server, the server is already listening for it and waiting. When a server wants to send something, then client is ready and waiting. So everything is OK! It all works just fine! WITH ONE BIG EXCEPTION.
Usually the server is in R mode and the client is in W mode. This is fine because user may send new data to server.
When a second client joins, all work fine. But when one of the clients sends a message to the server, the server needs to send the situation update to the other client. However, the other client is in WRITING mode and CANNOT accept the situation update Useful Data despite it is queued on the server. When something is done on the second client, the roles are swapped and the queued Useful Data is sent.
So obviously, there is a flaw in the operation mode when server is always R and client is always W.
My question is: Is there a way to organize the connection so that both sides could send and receive messages freely?
My only guess is to create two distinct channels for the two distinct directions s(W) -> с(R) and с(W) -> s(R) which will never change their interests. However, this seems a little strange to me... is there any BETTER way to organize this?
2