on the Relay i normally see split packets whenever there has been some lag. Because then after the lag is gone, I'll receive a big bunch of data all at once. And because that data may be bigger than the network buffer, it's just split at the buffer's boundary.
You can say it like this too : LFS always sends small packets. These are so small that they'll always fit into one network packet. Even if LFS needs to send several packets (like MCI) at once, 4 or 5 of them may still fit into one network packet. So these will not be split, but they will be concatenated -> a stream.
But now imagine there can be situations (lag / packet loss) where the amount of data exceeds the network packet's window size - then TCP will split the data after the network packet is full and continues with the data in the next TCP packet.
---
Ok now that I'm writing this anyway, I'd like to make a recommendation : (hm two it seems)
In your piece of network code you're constantly allocating memory for buff. This means the garbage collector will be doing a lot of work. Better create a byte[] buffer once (when you construct the networking class) and use that for all your network buffer reading needs.
In fact, I think reading byte for byte / packet for packet from the socket isn't good practise either. You're better off reading all the data in the network buffer asap, into a separate buffer. Then call a method that processes that data buffer to find the next valid packet.
That way your socket buffer will be more available, because you empty it completely as soon as you detect that it holds any data. Under stress, this allows the kernel to quickly fill the buffer again, keeping the data flow between two sockets going quicker.
So :
-create one buffer property in the class, where you read network data into. I would make it 4KB in size.
-always read the entire data in socket's buffer into our local buffer.
-after reading all data from socket, process the buffer to find the next packet(s)