Receiving & Converting Numeric and String Data via Sockets

Many times, a remote system will send a numeric value indicating the length of the data to be received in subsequent receive commands. However, when you start sending and receiving numeric data via sockets, you have to be aware of conversion issues in terms of what type of machine is on the other end of the connection. Specifically, you need to know how to convert numeric data from the local machine’s format (host order) to the industry standard format for sending sockets data (network order).

Note: If the terms host order, network order, little-endian, or big-endian are new to you or you’d like a refresher on these terms, please refer to my article entitled “Sockets Byte-Ordering Primer”.

Use the IPAddress.NetworkToHostOrder method to convert data from network order to the host order (local machine format). To illustrate its use, here is a ReceiveHeader function where I’m performing the following tasks:

  • Receive the data from the remote machine via the Socket.Receive method.
  • Verify that the bytes received are exactly 4.
  • The Socket.Receive method returns a byte array so the sample converts that into a numeric value, using the BitConvert.ToInt32 method.
  • Finally, the IPAddress.NetworkToHostOrder method converts the length value to the host order.
public int ReceiveHeader(Socket socket)
{
   int dataSize = -1;    // error
   byte [] buffer = new byte[4];

   int bytesRead = socket.Receive(buffer, 4,
                   System.Net.Sockets.SocketFlags.None);

   if (4 == bytesRead)
   {
      dataSize = BitConverter.ToInt32(buffer, 0);
      dataSize = IPAddress.NetworkToHostOrder(dataSize);
   }
   else    // error condition

   return dataSize;
}

Now, let’s look at how to receive string data from a remote machine with multiple reads where each string is to be concatenated. In this case, there are no issues of little-endian vs. big-endian as that pertains to numeric data conversion. Instead, you may have a situation where you need to convert from a byte buffer to a String object. You can execute the conversion by using either the ASCIIEncoding or UnicodeEncoding classes depending on your needs. In the ReceiveDetail function, I perform the following steps (remember that this function was called after the ReceiveHeader function from the previous section. Therefore, the datasize value was retrieved from that function.):

  • From a while loop, call Socket.Receive until no bytes are returned. The data is read into a byte array.
  • Instantiate an ASCIIEncoding object.
  • Call the ASCIIEncoding.GetString value to convert the byte array into a String object and then concatenate that value with the previously read data.
public string ReceiveDetail(Socket socket, byte[] buffer,
                            int dataSize)
{
   string response = "";

   int bytesReceived         = 0;
   int totalBytesReceived    = 0;
   while (0 < (bytesReceived =
          socket.Receive(buffer, (dataSize - totalBytesReceived),
                                  SocketFlags.None)))
   {
      totalBytesReceived += bytesReceived;
      ASCIIEncoding encoding = new ASCIIEncoding();
      response += encoding.GetString(buffer, 0, bytesReceived);
   }

   return response;
}

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read