title: How to determine behavior of TCP/IP stack in C#
body: <p>I have been facing slow client message consuming in client/server app using TCP sockets in c#. Whenever slow client is connected to server, it affects the processing of other clients. </p>
  
  <p>After reading some literature regarding tcp/ip stack in c#, i concluded that due to RCV_BUFFER full at client side and SND_BUFFER full at server side, other clients are affecting.   </p>
  
  <p>Although i couldn't produce the scenario in real environment, so here is what i have done for simulating slow client message processing. </p>
  
  <ol>
  <li>Created sample application for client and implemented the sleep for 1 to 10 seconds before reading it from RCV_BUFFER (so it can be full).  </li>
  <li>Connecting two clients (one with varying sleep time while other with no sleep time). </li>
  </ol>
  
  <p>I saw that client with  no sleep time is affecting but i couldn't determine the pattern of this problem.</p>
  
  <p>Here are some queries, i want to clear confusion on my side.
   1. How to determine the size of SND_BUFFER before sending the data to TCP SEND_WINDOW at server side. 
   2. What steps should i take to determine the pattern of problem. So i can proceed to solution. </p>
  
  <p>Here are code snippets for Server Side.</p>
  
  <pre><code>public bool Start()
  {
      try
      {
          _listener.Bind(new IPEndPoint(IPAddress.Any, _port));
          _listener.Listen(2000);
          _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
          _listener.BeginAccept(ConnectionReady, null);
          LogHelper.ErrorLogger.Debug("Listening started");
          return true;
      }
      catch
      {
          return false;
      }
  }
  
  public void createSession(object obj)
  {
      Socket conn = (Socket)obj;
      try
      {
          LogHelper.ErrorLogger.Debug("Creating Session");
          ConnectionState st = new ConnectionState(conn); // Custom class for maintaining the socket object
          st._server = this;
          st._provider = _provider;
          st._buffer = new byte[4];
          st._provider.OnAcceptConnection(st);
          AcceptConnection.BeginInvoke(st, null, st);
          LogHelper.ErrorLogger.Debug("Session Created");
      }
      catch (Exception ex)
      {
          try
          {
              conn.Close();
          }
          catch { }
          LogHelper.ErrorLogger.Debug("Session aborted -          &gt;" + ex.ToString());
      }
  }
  
  private void AcceptConnection_Handler(object state)
  {
      try
      {
          ConnectionState st = state as ConnectionState;
          try
          {
              st.AuthenticateSocket();
  
              //Starts the ReceiveData callback loop
              if (st._conn.Connected)
                  st._conn.BeginReceive(st._buffer, 0, 0, SocketFlags.None, ReceivedDataReady, st);
          }
          catch
          {
              DropConnection(st);
          }
      }
      catch { }
  }
  
  private void ReceivedDataReady_Handler(IAsyncResult ar)
  {
      try
      {
          ConnectionState st = ar.AsyncState as ConnectionState;
          try
          {
              try
              {
                  int bytesRcv = st._conn.EndReceive(ar);
                  //Encoding.UTF8.GetString(buffer, 0, readBytes);
                  //state.msgBuffer.Append(_receivedStr);
              }
              catch
              {
                  DropConnection(st); return;
              }
              //Im considering the following condition as a signal that the
              //remote host droped the connection.
              if (st._conn.Available == 0)
              {
                  DropConnection(st);//@@SHARIQ
                  return;
              }
              else
              {
                  try
                  {
                      st._provider.OnReceiveData(st);
                  }
                  catch
                  {
                      return;
                  }
                  //Resume ReceivedData callback loop
                  if (st._conn.Connected)
                      st._conn.BeginReceive(st._buffer, 0, 0, SocketFlags.None, ReceivedDataReady, st);
              }
          }
          catch { DropConnection(st); return; }
      }
      catch { }
  }
  </code></pre>
  
  <p>Message is fetched from MSMQ (a thread is running to fetch messages from MSMQ through receiver object), and whenever message is fetched following event is fired and extracts ip addresses from messages and send one message to socket(s).</p>
  
  <pre><code>private void m_broker_OnMessage(object obj)
  {
      try
      {
          Message m = (Message)obj;
          m.Formatter = new BinaryMessageFormatter();
          ConnectionState tstate = null;
          bool containststate = false;
          string TempLabels = string.Empty;
          string BodyMessage = string.Empty;
          if (m.Body.ToString().StartsWith("="))
          {
              BodyMessage = (string)m.Body;
              TempLabels = BodyMessage.Substring(1, BodyMessage.IndexOf('#') - 1);
              BodyMessage = BodyMessage.Substring(BodyMessage.IndexOf('#') + 1);
          }
          if (!string.IsNullOrEmpty(TempLabels))
          {
              string[] labels = TempLabels.Split(',');
              foreach (string label in labels)
              {
                  lock (cons)
                  {
                      containststate = cons.Contains(label);
                      if (containststate)
                      {
                          tstate = (ConnectionState)cons[label];
                      }
  
                  }
                  if (containststate)
                  {
                      ConnectionState state = tstate;
                      if (!state.WriteLine(BodyMessage + "1057=" + label + "#"))
                      {
                          OnDropConnection(state);
                          continue;
                      }
                      if (ConfigurationSettings.AppSettings["FullLog"] == "1")
                      {
                          eventLogger.Debug("OUT " + label + " " + BodyMessage);
                      }
                  }
                  else
                  {
                      long result;
                      if (!lastResolve.Contains(label))
                      {
                          if ((!string.IsNullOrEmpty(label)) &amp;&amp; long.TryParse(label, out result))
                          {
                              if (ConfigurationSettings.AppSettings["FullLog"] == "1")
                              {
                                  eventLogger.Info("Label not found: " + label);
                              }
                              string msg = "8=EXX.1.0#35=C7#1057=" + label + "#";
                              this.Send(msg, label, "0.0.0.0");
                              eventLogger.Info("Connection Disconnected: " + label);
                              //Nothing to clean here
                              lock (cons)
                              {
                                  if (cons.Contains(label))
                                  {
                                      try
                                      {
                                          string ipaddress = ((ConnectionState)cons[label]).RemoteEndPoint.ToString().Split(':')[0];
                                          connectionGroups[ipaddress]--;
                                      }
                                      catch { }
                                  }
                                  cons.Remove(label);
                                  lastResolve.Add(label);
                              }
                          }
                      }
                      continue;
                  }
              }
          }
          else
          {
              lock (cons)
              {
                  containststate = cons.Contains(m.Label);
                  if (containststate)
                  {
                      tstate = (ConnectionState)cons[m.Label];
                  }
  
              }
              if (containststate)
              {
                  ConnectionState state = tstate;
                  if (!state.WriteLine((string)m.Body + "1057=" + m.Label + "#"))
                  {
                      OnDropConnection(state);
                      return;
                  }
                  if (ConfigurationSettings.AppSettings["FullLog"] == "1")
                  {
                      eventLogger.Debug("OUT " + m.Label + " " + m.Body.ToString());
                  }
              }
              else
              {
                  long result;
                  if (!lastResolve.Contains(m.Label))
                  {
                      if ((!string.IsNullOrEmpty(m.Label)) &amp;&amp; long.TryParse(m.Label, out result))
                      {
                          if (ConfigurationSettings.AppSettings["FullLog"] == "1")
                          {
                              eventLogger.Info("Label not found: " + m.Label);
                          }
                          string msg = "8=EXX.1.0#35=C7#1057=" + m.Label + "#";
                          this.Send(msg, m.Label, "0.0.0.0");
                          eventLogger.Info("Connection Disconnected: " + m.Label);
                          //Nothing to clean here
                          lock (cons)
                          {
                              if (cons.Contains(m.Label))
                              {
                                  try
                                  {
                                      string ipaddress = ((ConnectionState)cons[m.Label]).RemoteEndPoint.ToString().Split(':')[0];
                                      connectionGroups[ipaddress]--;
                                  }
                                  catch { }
                              }
                              cons.Remove(m.Label);
                              lastResolve.Add(m.Label);
                          }
                      }
                  }
                  return;
              }
          }
      }
      catch (Exception e)
      {
          errorLogger.Error(e.Message, e);
      }
  }
  </code></pre>
  
  <p>Sending is done in blocking manner</p>
  
  <pre><code>public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags)
  {
      lock (sendObject)
      {
          try
          {
              if (_innerSocketStream.IsUsingSsl)
              {
  
                  myStream.Write(buffer, offset, size);
              }
              else
              {
                  _innerSocketStream.Socket.Send(buffer, offset, size, SocketFlags.None);
              }
          }
          catch (SocketException)
          {
              return 0;
          }
          return size;
      }
  }
  </code></pre>