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?

Looks like you've got a good understanding of how socket channels work. Took me weeks to understand them Yes, if you use TCP (Socket, SocketChannel) the underlying OS/socket protocol stack will arbitrarily decide when to send a packet, you can somewhat affect this by calling flush if you are using a Socket, but I'd have to do some research. The JavaDoc for OutputStream's flush() method mentions:

Quote

If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive.

However, this doesn't really apply to SocketChannel's read() or write() method. So I'm not sure that there are any guarantees about the behavior of either method.

If you use a DatagramSocket or DatagramChannel and keep the data you write under the maximum UDP transmission size, then the write methods will almost always send one packet per each write() method call, although it may vary from OS to OS.

So yes, the behavior you are describing is expected. One way around it is to use a special marker byte/character between packets. However, if the data in your packets might contain that special marker, then you will need to use an escape marker for your special marker to differentiate between the end of a packet and a marker that happens to be data in the packet.

Another solution is to include the length of the packet at the beginning of each packet, this way you don't need any special markers or escape markers. Just read the length whenever you receive data and keep reading until number-of-bytes-read == length, then read the next packet's length and so on.

You could also additionally or instead put the length of the packet at the start so you know when the packet has been read fully and prepare for the next packet. This has the benefit of you knowing when to stop reading and e.g. check if the packet length is something ridiculously large and skip it.

Upon my recommendation (claim to fame!), Nate used chucked encoding in Kryo. This allows streaming of data without knowing the packet length ahead of time, and equally reading back the stream without holding it in memory.

With chunked encoding you basically say that the current message has N more bytes, and after N bytes you send the size of the next chunck. A chuck size of 0 signals the end of the message.

Hi, appreciate more people! Σ ♥ = ¾Learn how to award medals... and work your way up the social rankings!

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org