I have my networking code set up so if we wish to send data we simply add it to the queue and mark the selectionkey for OP_WRITE
public void send( byte[] message) throws IOException{
if(this.socketChannel == null){
throw new SocketException("Socket connection has closed!");
}
messages.add(message);
selectionKey = selectionKey.interestOps(SelectionKey.OP_WRITE);
}
in my handleWrite() method I simply loop over all the data we find in the queue and send it
public void handleWrite(SelectionKey key) throws IOException
{
this.socketChannel = (SocketChannel) key.channel();
//error checking removed to conserve space
while (!messages.isEmpty()) {
writeBuffer = ByteBuffer.wrap(messages.peek());
if(socketChannel.write(writeBuffer) == 0){
break;
}
if (writeBuffer.remaining() > 0) {
break;
}
writeBuffer.compact();
messages.remove(); //everything went well so remove head
}
selectionKey.interestOps(SelectionKey.OP_READ);
}
in my read method I simply take the bytes I get and transform it into a packet object
public Packet handleRead(SelectionKey key, PacketFactory factory) throws IOException{
this.socketChannel = (SocketChannel) key.channel();
//error checking removed to conserve space
int bytesRead = 0;
readBuffer.clear();
try {
bytesRead = this.socketChannel.read(readBuffer);
readBuffer.flip();
} catch (IOException e) {
log.message("connection closed at: " + this.socketChannel.getRemoteAddress(), Log.INFO);
key.cancel();
close();
}
//error checking removed to conserve space
byte[] data = readBuffer.array();
return factory.buildPacket(transformer.getType(data), transformer.getData(data));
}
my problem arises from the fact of when there are mutliple messages in the queue. So lets say I have requested to send a packet 3 times [3]:FOO:[3]:BAR, [3]:FOO:[3]:BAR, [3]:FOO:[3]:BAR. I would expect my read to be called 3 times and return 3 FOO packets with each one having the arguments BAR. Instead it returns 1 big packet FOO with the arguments BAR,FOO,BAR,FOO,BAR.
whats the best way to split this up? Have I done something wrong with my reading and writing or is this behavour to be expected? should I instead change my protocol so packets have a termination character so we know when a new packet begins?