I have two applications (a server and a client) that talk to each other via TCP/IP. (WinXP to WinXP) I've noticed that if the server runs on a relatively poor performing machine and the TCP/IP traffic is high, that TCP/IP will be smart and combined messages to save on network traffic. My server/client are able to handle that just fine; however, I've recently noticed that in certain circumstances, like over a VPN connection where the network performance is degraded, TCP/IP will not only combined packets, but will also split the packets. That is to say where one packet was sent, two are received. In reality what happens is that four are sent and two are received; the first 3 are combined with 1/2 of the fourth and the other half of the fourth is in the second packet. This wouldn't be a problem except I don't know how to know which packets need to be reconnected and in what order. This seems to only occur when a large number of packets are being sent in rapid succession. TCP/IP does not guarantee that the order sent is the order received. The data that is being sent must pieced together in the correct order for it to be useable.
Is this normal behavior and if so, how do you make the connection between packets?
TCP is stream oriented. The order of the bytes going in one side always remains the same when it comes out the other side. At the application level there are no packets. Packets come into play after TCP gets your data and transmits it. It is free to do whatever is needed to get the bytes from one place to another -- split, combine, distribute amongst several homing pigeons, whatever. The bytes can arrive on the other side in any order but they are always reassembled in the sending order prior to presentation to the application.
I'm guessing you are sending messages of specific lengths over the socket and most of the time when you do a write on one side, your read on the other side gets the full message in one chunk. This is not always the case. When the receiver does a read(), all of the bytes in the stream may not have arrived yet and you will come up short or bytes from a following message may have arrived and you will get part of the next message. This is normal. You can't prevent it from happening. Assuming there is a one to one coorespondence between reads and writes is a very common mistake. It usually works when you are on the test bench but when things get busy, it all falls apart.
Typically what is done is to add some structure to your messages. Start them with some sort of Start of Message marker followed by the message length. The receiver reads this header portion and then reads again for the indicated length. The read may come up short in which you have to dip in again waiting for additional bytes. Once length bytes have been read, the next read should be for a message header again and the process repeats.
Thanks for the very helpful reply. This confirms what I had surmised. I'll check out the book too; I've run into many problems along the way that has been quite frustrating. I'm considering a re-write of the server side in Java for it's cross platform compatibility and so I'd like as much information up front during the design phase.