Nova
Nova

Reputation: 31

Split messages over tcp

Im having a little trouble in a uni project. Im sending a tcp message from a C++ client to a C# server and the server is receiving it in 2 parts. Is it possible to stop it from down this? I output the data being sent in my client and all the data is in 1 piece so it cant be this. Here is my OnReceiveData method:

void OnReceiveData(IAsyncResult result){
        try{
            int readbytes = myStream.EndRead(result);
            if (readbytes <= 0){
                //client is not connected to the server anymore
                CloseSocket();
                return;


            byte[] newBytes = new byte[readbytes];
            Buffer.BlockCopy(readBuff, 0, newBytes, 0, readbytes);
            myStream.BeginRead(readBuff, 0, readbytes, OnReceiveData, 
            null);
            string output = 
            System.Text.Encoding.ASCII.GetString(newBytes, 0, 
            readbytes);
            Text.WriteLog(output);

            ServerHandleData.HandleData(connectionID, newBytes);
        }
        catch (Exception e)
        {
            Text.WriteError("Error Code: " + e);
            CloseSocket();
        }
    } 

Thanks!

Upvotes: 3

Views: 1914

Answers (3)

the_storyteller
the_storyteller

Reputation: 2487

No, a TCP is a stream, not a single "chunk" of data.

As seen in the EndRead example, a message may be read in multiple parts, so you'll have to read the parts and concatenate them.

readbytes = myStream.EndRead(result);
myCompleteMessage = String.Concat(myCompleteMessage,
                                  Encoding.ASCII.GetString(myReadBuffer, 0,
                                                           readbytes));    

// message received may be larger than buffer size so loop through until you have it all.
while(myStream.DataAvailable) {

    myStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length,
                       new AsyncCallback(NetworkStream_ASync_Send_Receive.myReadCallBack),
                                         myStream);  
}

Upvotes: 1

Nova
Nova

Reputation: 31

So after some time I managed to fix it. The issue was the read bytes in the begin read was being set to the previous message length which was forcing it to split the message. I fixed it by manually setting the size.

Thanks for the advice guys! :)

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409176

No there's no way to "stop it", that's simply how the streaming TCP work.

In short, since TCP is streaming there are no message boundaries. It's just a continuous stream of bytes.

To implement some kind of messaging or boundaries between the data, then you need to come up with your own application-layer protocol to put on top of TCP. For example you could introduce some kind of message boundary token, a special character, byte, or sequence of characters/bytes that means the current message have ended. Or you could send a fixed-size message-header that includes the size of the actual message data.

Then when receiving you need to receive in a loop until you detect the end of the message. For this the simplest way is the fixed-size header with the data-length, as then you simply attempt to read the length (of the header or of the data), decreasing the number of bytes to receive each iteration, until there's nothing more to receive (the number of bytes to receive reaches zero).

Upvotes: 1

Related Questions