Hello,
I use Java NIO, non blocking for my client-server program.
Everything works ok, until there are many clients that sending messages at the same time to the server.
The server can identify all the clients, and begin reading, but the reading of those multiple clients are always the same message.
For example, client A send "Message A", client B send "Missing Message", client C send "Another Missing Message" at the same time to the server, the server read client A send "Message A", client B send "Message A", client C send "Message A", only happen if the server trying to read all those messages at once, if the server read one by one, it's working perfectly.
What's wrong with my code?
This is on the server, reading the message:
private Selector packetReader; // the selector to read client message
public void update(long elapsedTime) throws IOException {
...
if (packetReader.selectNow() > 0) {
// message received
Iterator packetIterator = packetReader.selectedKeys().iterator();
while (packetIterator.hasNext()) {
SelectionKey key = (SelectionKey) packetIterator.next();
packetIterator.remove();
// there is client sending message, looping until all clients message
// fully read
// construct packet
TCPClient client = (TCPClient) key.attachment();
try {
client.read(); // IN HERE ALL THE CLIENTS READ THE SAME MESSAGES
// if only one client send message, it's working, if there are multiple selector key, the message screwed
} catch (IOException ex) {
// ex.printStackTrace();
removeClient(client); // something not right, kick this client
}
}
}
On the client, I think this is the culprit :
private ByteBuffer readBuffer; // the byte buffer
private SocketChannel client; // the client SocketChannel
protected synchronized void read() throws IOException {
readBuffer.clear(); // clear previous buffer
int bytesRead = client.read(readBuffer); // THIS ONE READ THE SAME MESSAGES, I think this is the culprit
if (bytesRead < 0) {
throw new IOException("Reached end of stream");
} else if (bytesRead == 0) {
return;
}
// write to storage (DataInputStream input field storage)
storage.write(readBuffer.array(), 0, bytesRead);
...
// in here the construction of the buffer to real message
}
How could the next client read not from the beginning of the received message but to its actual message (client.read(readBuffer)), i'm thinking to use SocketChannel.read(ByteBuffer[] dsts, , int offset, int length) but don't know the offset, the length, and what's that for :(
Anyone networking gurus, please help...
Thank you very much.