Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TCP listener cuts message at 1024 bytes

Problem just started on client side. Here is my code where I receive TCP/IP message. On my local PC this listener receives many K no problem. I tried to increase buffer size but on client site they still report issues related to it.. Still get's only first 1K (1024 bytes)

public void Start()
{
  //Define TCP listener
  tcpListener = new TcpListener(IPAddress.Any, IDLocal.LocalSession.PortNumber);

  try
  {
    //Starting TCP listenere
    tcpListener.Start();

    while (true)
    {
      var clientSocket = tcpListener.AcceptSocket();
      if (clientSocket.Connected)
      {
        var netStream = new NetworkStream(clientSocket);

        // Check to see if this NetworkStream is readable.
        if (netStream.CanRead)
        {
          var myReadBuffer = new byte[1024];
          var myCompleteMessage = new StringBuilder();

          // Incoming message may be larger than the buffer size.
          do
          {
            var numberOfBytesRead = netStream.Read(myReadBuffer, 0, myReadBuffer.Length);
            myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
          } while (netStream.DataAvailable);

          //All we do is response with "OK" message
          var sendBytes = Encoding.ASCII.GetBytes("OK");
          netStream.Write(sendBytes, 0, sendBytes.Length);

          clientSocket.Close();
          netStream.Dispose();

          // Raise event with message we received
          DataReceived(myCompleteMessage.ToString());
        }
      }
    } 
  }
  catch (Exception e)
  {
    //If we catch network related exception - send event up
    IDListenerException(e.Message);  
  }
}
like image 747
katit Avatar asked Jun 16 '11 15:06

katit


1 Answers

I don't see any problem with the code you posted to extract the message into a string, so I 'm guessing that something else is afoot.

TCP isn't required to send all data you queue to it in one go. This means it can send as few as it want to at a time, and it can choose to split your data into pieces at will. In particular, it is guaranteed to split your data if they don't fit into one packet. Typically, the maximum packet size (aka MTU) is 1532 bytes IIRC.

Therefore there's a real possibility that the data is sent, but as more than one packet. The delay between reception of the first and second packet could mean that when the first one arrives your code happily reads everything it contains and then stops (no more data) before the second packet has had time to arrive.

You can test this hypothesis by either observing network traffic, or allowing your app to pull more messages from the wire and see if it finally does get all the data you sent (albeit in pieces).

Ultimately the underlying issue is TCP's fundamental stream-based (and not message-based) nature; even if you get this code to work correctly, there is no guarantee that it will continue working in the future because it makes assumptions about stuff that TCP does not guarantee.

To be safe, you will need to incorporate a message-based structure (e.g. prepending each piece of data with exactly 4 bytes that hold its length; then, you can just keep reading forever until you have received that many bytes).

like image 56
Jon Avatar answered Sep 26 '22 17:09

Jon