Simple Message Framing Sample for TCP Socket

A common misunderstanding for developers new to network programming over TCP sockets is how messages are sent and received.  I frequently hear the statement that “my data is not arriving on the other side of the socket in the same format that I sent it.”  The most common cause of this is because the TCP protocol does not guarantee that it will keep message boundaries.  In other words, you could send “Hello World” in a single call to Send(), but the other side of the socket stream may have to do multiple Receive() calls on the socket to get all of the data (the first Receive might return “He” and the second “llo World”).  Data might also be concatenated together into a single TCP packet on the wire.  The client may send “Hello World”  and “I am in Seattle” in different calls to Send(), but the other side of the socket may receive it with a single call to Receive() in the format “Hello WorldI am in Seattle”.

I thought I would give a simple example that shows how to frame your message so that it comes out on the other side of the network stream in the same format in which it was sent.  Your implementation may need to be more complex than what I have given here. 

Also, I have written this in C# and please be aware that this code does not handle errors in the stream and does not do parameter checking.  If the connection get’s dropped in the middle of a mesage or if the msg being sent is greater than what can be sent with an integer size, you will see funny results.  Here, I am trying to keep the code simple and to the point.

      static void SendMessage(Socket socket, string msg)
            byte[] data = Encoding.ASCII.GetBytes(msg);
            byte[] sizeinfo = new byte[4];

            //could optionally call BitConverter.GetBytes(data.length);
            sizeinfo[0] = (byte)data.Length;
            sizeinfo[1] = (byte)(data.Length >> 8);
            sizeinfo[2] = (byte)(data.Length >> 16);
            sizeinfo[3] = (byte)(data.Length >> 24);


        //note, this function does not handle closed connections in the middle of a message…
        static string ReadMessage(Socket socket)
            byte[] sizeinfo = new byte[4];

            //read the size of the message
            int totalread = 0, currentread = 0;

            currentread = totalread = socket.Receive(sizeinfo);

            while (totalread < sizeinfo.Length && currentread > 0)
                currentread = socket.Receive(sizeinfo,
                          totalread, //offset into the buffer
                          sizeinfo.Length – totalread, //max amount to read

                totalread += currentread;

            int messagesize = 0;

            //could optionally call BitConverter.ToInt32(sizeinfo, 0);
            messagesize |= sizeinfo[0];
            messagesize |= (((int)sizeinfo[1]) << 8);
            messagesize |= (((int)sizeinfo[2]) << 16);
            messagesize |= (((int)sizeinfo[3]) << 24);
            //create a byte array of the correct size
            //note:  there really should be a size restriction on
            //              messagesize because a user could send
            //              Int32.MaxValue and cause an OutOfMemoryException
            //              on the receiving side.  maybe consider using a short instead
            //              or just limit the size to some reasonable value
            byte[] data = new byte[messagesize];

            //read the first chunk of data
            totalread = 0;
currentread = totalread = socket.Receive(data,
                         totalread, //offset into the buffer
                        data.Length – totalread, //max amount to read

            //if we didn’t get the entire message, read some more until we do
            while (totalread < messagesize && currentread > 0)
                currentread = socket.Receive(data,
                         totalread, //offset into the buffer
                        data.Length – totalread, //max amount to read
                totalread += currentread;


            return Encoding.ASCII.GetString(data, 0, totalread);                   

I would also recommend that you read Malar Chinnusamy’s blog on socket programming considerations 

Comments (11)

  1. Recently, Jon Cole from the System.Net&amp;nbsp;QA team posted a great article in response to&amp;nbsp;questions…

  2. Ioan Herisanu says:

    If you send "Hello World" and receive "he" + "llo world" then you have not a TCP socket.  For TCP one should have received "He" + "llo World". Please, pay attention when working with these,as some novices will understand really bad things

  3. Alan McFarlane says:

    I’ve seen very many people misuenderstanding this and have answered many myself and agree with you diagnosis.  However your send side code provokes bad behaviour, almost guaranteeing that your readers’ next question is "How do I turn off Nagle?  As the performance sucks…"

    By doing send(), send(), the stack will send the first chunk (the length), wait for TCP ACK before sending the second chunk (the data).  Thus breaking another of the cardinal TCP programmer rules, "Send *all* related data in one send()".  See e.g.  and

    Perhaps you can cover such subjects in subsequent postings. :-)


  4. joncole says:

    Ioan,  You are correct.  I definitely had a type-o in my explanation and I have fixed the mistake.

  5. joncole says:

    Alan,  Good feedback.  I considered writing the code as you mention to eliminate the duplicate calls to Send(), but I purposely made the decision to leave the duplicate calls in to emphasize the fact that the message size is sent as a "prefix" to the actual message.  I will add a note to the post to encourage people to read the comments you have posted.

  6. Denis says:

    While Alan is correct that this is one scenario is possible with Send(), Send() it makes it appear as if this is deterministic when it is in fact not. If you send two buffers (B1 and B2) the following are some of the possible scenarios:

    1. B1 is sent as one segment and B2 is sent as another over the wire.

    2. B1 and B2 are coalesced into one segment that is sent over the wire

    3. Part of B1 is sent in one segment, and the remaining bits are sent along with B2 in another segment.

    4. B1 and part of B2 are sent in one segment followed by the rest of B2 in another segment.

    Many factors come into play. If the Nagle algorithm is disabled, the behavior will be different. If the connection is waiting for an ACK, buffers will likely be coalesced. etc…

    The important points are:

    1. As Alan stated, the Send(header), Send(payload) is probably not a good idea.

    2. TCP is a stream protocol. Message boundaries are not guaranteed.

  7. valkyrie says:

    Thank you.  That was the most suscint framing of this particular conversation I have ever seen.

    Thank you again.


  8. Sean Beebe says:

    Hi Jon,

    Thanks for the example. It was very helpful for me.

    Also, I think I may have discovered a bug. In the second while loop of ReadMessage shouldn’t totalread += currentread come after the socket.Receive.



  9. joncole says:


    Yes, you are correct that I needed to put that line after the Socket.Receive inside the while loop.  Also, I noticed I was using the wrong offset into the data buffer for that first read of the message body.  I have fixed both problems in the sample code above.  

    Thanks for taking the time to point this out,

  10. verygis says: