title: How to prevent Stack Overflow Exception due to an async ReceiveCallback (TCP Server)
body: <p>I'm working on a Server-Client application with TCP and Sockets
  The communication works fine and all and the messages arrive correctly.
  The way I made this is:</p>
  <ol>
  <li>a packet arrives and gets written into a client specific buffer The first 10 characters is the length of the message, the rest is
  the message (JSON-string)</li>
  <li>if the buffer is the same length as the message CheckIfMessageArrivedCompletely(Socket client ) gets executed which does whatever the message includes (the message is a JSON object in which it contains a path element which is inserted into the &quot;forwardingDictionary&quot;</li>
  <li>if the buffer is shorter wait until everything arrived.</li>
  </ol>
  <p>Now onto the problem:
  Since The new socket.BeginReceive and therefore the AsyncCallback is called within the old AsyncCallback it is recursive. After about 2000 times the program throws the Stack Overflow exception. This is somewhat logical even if the function only is called after a packet arrives. But how can this be prevented. The goal is to have a continuously open Socket which is able to receive Data. This is especially a problem when sending a file (converted to byte[] ) over ~20kb.</p>
  <p>I'm new to networking, so if you would see any rookie mistake feel free to correct me.
  I would really appreciate it.</p>
  <p>This is the code responsible for the networking:</p>
  <pre><code>public static void InitializeServer(){
      //---listen at the specified IP and port no.---
      Console.WriteLine(&quot;Starting Server...&quot;);
      Console.WriteLine(&quot;Listening...&quot;);
  
      serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT_NO));
      serverSocket.Listen(NUM_OF_PLAYERS); //the maximum pending client
      serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null);      
      string result = &quot;&quot;;
      do {
          result = Console.ReadLine();
      } while (result.ToLower().Trim() != &quot;exit&quot;);
  }
  
  
  private static void acceptCallback(IAsyncResult result) { 
      Socket socket = null;
  
      try {
          socket =serverSocket.EndAccept(result);
  
          Console.WriteLine(socket.RemoteEndPoint.Serialize());
  
          //Do something as you see it needs on client acceptance
          buffer.Add(socket,new byte[BUFFER_SIZE]);
          socket.BeginReceive(buffer[socket], 0, buffer[socket].Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
          serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null); //to receive another client
      } catch (Exception e) {        
          Console.WriteLine(e.ToString());
      }
  }
  private const int BUFFER_SIZE = 10000;
  private static Dictionary&lt;Socket,byte[]&gt; buffer = new Dictionary&lt;Socket, byte[]&gt;();
  private static Dictionary&lt;Socket,byte[]&gt; messageBuffer = new Dictionary&lt;Socket, byte[]&gt;();
  const int MAX_RECEIVE_ATTEMPT = 10;
  static int receiveAttempt = 0; 
  private static void receiveCallback(IAsyncResult result) {
      Socket socket = null;
      try {
          socket =(Socket)result.AsyncState;
          if (socket.Connected) { //simple checking
              int received = socket.EndReceive(result);
              if (received &gt; 0) {
                  Console.Write(&quot;.&quot;); //to log incoming packet;
                  //Check if Client has an unfinished Packet
                  int lastNonZeroIndex = Array.FindLastIndex(buffer[socket],x =&gt; x != 0);
                  if(messageBuffer.ContainsKey(socket)){
                      int firstNullIndex = Array.FindIndex(messageBuffer[socket], x =&gt; x == 0);
                      //Copy the incoming data at the end of the buffer
                      Buffer.BlockCopy(buffer[socket],0,messageBuffer[socket],firstNullIndex,lastNonZeroIndex+1);
                  }
                  else{
                      //Since it's a new message, parse its length and add the empty byte to the dictionary
                      int messageLength = int.Parse(new string(Encoding.UTF8.GetChars(buffer[socket])).Substring(0,10));
                      messageBuffer.Add(socket,new byte[messageLength]);
                      Console.WriteLine(messageLength);
                      //Copy the incoming data at the end of the buffer
                      Array.Copy(buffer[socket],10,messageBuffer[socket],0,lastNonZeroIndex+1-10);
                  }
                  CheckIfMessageArrivedCompletely(socket);
                  Array.Clear(buffer[socket]);
                  receiveAttempt = 0; //reset receive attempt
                  socket.BeginReceive(buffer[socket], 0, buffer[socket].Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
              } else if (receiveAttempt &lt; MAX_RECEIVE_ATTEMPT) { //fail but not exceeding max attempt, repeats
                  ++receiveAttempt; //increase receive attempt;
                  socket.BeginReceive(buffer[socket], 0, buffer[socket].Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
              } else { //completely fails!
                  Console.WriteLine(&quot;receiveCallback fails!&quot;); //don't repeat beginReceive
                  receiveAttempt = 0; //reset this for the next connection
              }
          }
      } catch (Exception e) { // this exception will happen when &quot;this&quot; is be disposed...
          Console.WriteLine(&quot;receiveCallback fails with exception! &quot; + e.ToString());
      }
  }
  static void CheckIfMessageArrivedCompletely(Socket client){
      //if The Message arrived completely, execute the command and remove the message from the client buffer
      if(!messageBuffer.ContainsKey(client)){
          Console.WriteLine(&quot;ERROR: client not in dictionary&quot;);
          return;
      }
      if(messageBuffer[client][messageBuffer[client].Length-1] == 0)return; // if not completed return and wait for the rest
      //Convert bytes to string and then parse JSON 
      string strData = new string(Encoding.UTF8.GetChars(messageBuffer[client]));
      messageBuffer.Remove(client); // removing the bytes from the buffer
      JObject messageInJObject = JObject.Parse(strData);
      string[] command = messageInJObject[&quot;path&quot;].ToObject&lt;string[]&gt;();
      if(!forwardingDictionary.ContainsKey(command[0])) return; // if not in dictionary --&gt; return
      forwardingDictionary[command[0]](client,messageInJObject);
  }
  </code></pre>
  <p>The error looks like this:</p>
  <pre><code>Stack overflow.
     at System.Text.OSEncoding.WideCharToMultiByte(Int32, Char*, Int32, Byte*, Int32)
     at System.Text.OSEncoder.GetBytes(Char*, Int32, Byte*, Int32, Boolean)
     at System.Text.Encoder.GetBytes(System.ReadOnlySpan`1&lt;Char&gt;, System.Span`1&lt;Byte&gt;, Boolean)
     at System.IO.StreamWriter.Flush(Boolean, Boolean)
     at System.IO.StreamWriter.Write(System.String)
     at System.IO.TextWriter+SyncTextWriter.Write(System.String)
     at System.Console.Write(System.String)
     at Program.receiveCallback(System.IAsyncResult)
     at System.Threading.Tasks.TaskToApm+TaskAsyncResult..ctor(System.Threading.Tasks.Task, System.Object, System.AsyncCallback)
     at System.Net.Sockets.Socket.BeginReceive(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.AsyncCallback, System.Object)
     at Program.receiveCallback(System.IAsyncResult)
  </code></pre>
  <p>And the last 3 lines repeated the number of times it took to cause the error (about 2000 times)</p>