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);

            socket.Send(sizeinfo); socket.Send(data); }

        //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 SocketFlags.None);

                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 SocketFlags.None);

            //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 SocketFlags.None); totalread += currentread; }

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

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