locked
TCP Client - messages going lost

    Question

  • Hello everybody,

    i have a problem with my tcpclient. My send receive messages going lost every second send for sending, and every sencond receive for receiving. Here the code:

      public class OUCClient
      {
        TcpClient m_client;
        bool conntected = false;
        byte[] bytes = new byte[4] { 1, 2, 3, 4 };
    
        public byte[] InBuffer;
        private byte[] OutBuffer;
        private int bufferSize;
    
        public event EventHandler DataReceived;
    
        public OUCClient(int bufferSize)
        {
          this.bufferSize = bufferSize;
          // Data received from PLC
          this.InBuffer = new byte[this.bufferSize];
          // Data to send to PLC
          this.OutBuffer = new byte[this.bufferSize];
    
          this.m_client = new TcpClient();
          this.m_client.ReceiveTimeout = 5;
          this.m_client.SendTimeout = 5;
    
          byte[] addrArray = new byte[4] { 192, 168, 2, 10 };
          IPAddress address = new IPAddress(addrArray);
    
          m_client.BeginConnect(address, 2000, new AsyncCallback(connectCallback), this.m_client.Client);
        }
    
        void connectCallback(IAsyncResult iar)
        {
          try
          {
            Socket myClient = (Socket)iar.AsyncState;
    
            myClient.EndConnect(iar);
    
            myClient.BeginReceive(InBuffer, 0, this.bufferSize, SocketFlags.None,
              new AsyncCallback(receiveCallback), this.m_client.Client);
            this.conntected = true;
          }
          catch (Exception ex)
          {
            this.conntected = false;
            throw new Exception("Exception from connectCallback: " + ex.Message);
          }
          
        }
    
        void receiveCallback(IAsyncResult iar)
        {
          try
          {
            Socket myClient = (Socket)iar.AsyncState;
            int recv = myClient.EndReceive(iar);
    
            onDataReceived(EventArgs.Empty);
    
            myClient.BeginReceive(InBuffer, 0, this.bufferSize, SocketFlags.None,
              new AsyncCallback(receiveCallback), this.m_client.Client);
          }
          catch (Exception ex)
          {
            this.conntected = false;
            throw new Exception("Exception from receiveCallback: " + ex.Message);
          }
        }
    
        void onDataReceived(EventArgs e)
        {
          if (DataReceived != null)
            DataReceived(this, e);
        }
    
        public void Disconnect()
        {
          m_client.Client.Disconnect(false);
        }
    
        public void Send(byte[] bytes)
        {
          NetworkStream stream = m_client.GetStream();
          stream.Write(bytes, 0, bytes.Length);
          m_client.Client.BeginSend(bytes, 0, this.bufferSize, SocketFlags.None,
            new AsyncCallback(sendCallback), this.m_client.Client);
        }
    
        void sendCallback(IAsyncResult iar)
        {
          try
          {
            Socket myClient = (Socket)iar.AsyncState;
            int sent = this.m_client.Client.EndSend(iar);
          }
          catch (Exception ex)
          {
            this.conntected = false;
            throw new Exception("Exception from sendCallback: " + ex.Message);
          }
        }
      }
    

    I dont know how is it possible. I tried to debbug and I sended to the client a 24byte message (my bufferSize) receiveCallback is called every second time I send my 24bytes to my client. I dont understand it. Did someone of you have the same or similar problem? Thank you for your help!

    Greets - Raphael

    Sunday, October 17, 2010 11:37 AM

All replies

  • TCP is stream-oriented protocol. It sends streams of bytes, not messages as you imagined. So most likely several of your "messages" are concatenated either in send buffer or in receive buffer, and you are not aware of this cause you don't check received data size etc.

    If you need an easy way to send messages over TCP, take a look at MsgConnect , message-oriented communication framework.
    Sunday, October 17, 2010 1:09 PM
  • Ok, I should say 'byte stream', sorry. Size of the byte-stream to send and the count of the bytes for one receive is constant. Async receive on my client is active permanet, so there is no possibility, that i miss somthing. Ive sent 24bytes from my server (without errors) and the receiveCallback wasn't called. First after second sent I received my 24bytes, but the first 24bytes ware lost... :(
    Sunday, October 17, 2010 3:43 PM
  • Add one line to your program.  Change it to have:

      try
      {
      Socket myClient = (Socket)iar.AsyncState;
      int recvLen = myClient.EndReceive(iar);
       if(recvLen != 24)
       throw new InvalidOperationException("Huh got different size of data than I assumed I was getting.");
    
      onDataReceived(EventArgs.Empty);
    
    
    

    See what occurs then... One *must* check the return value of Read/Receive, as TCP/IP is allowed to split data into different size chunks or to merge together chunks, or both...


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, mark the question answered
    Sunday, October 17, 2010 5:36 PM
  • Hello Alan,

    you don't understand... I do not even come to this callback, because the client didn't receive anything or something is configured wrong... Only every second time - 24Bytes (where 48 ware sent from the server)

    Greets - Raphael

    Wednesday, October 20, 2010 12:33 PM
  • Don't know how you're calling the class...  With the following I see the twenty-four bytes TWICE on the network (using a network sniffer)...  Presumably, once from the stream.Write and once from the Send.

      byte[] twentyFourBytes = { 24,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,0 };
      OUCClient cli;
      cli = new OUCClient(24);
      Console.Write("paused> ");
      Console.ReadLine();
      cli.Send(twentyFourBytes);
    
    

    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, mark the question answered
    Wednesday, October 20, 2010 8:12 PM