title: How can I efficiently receive & send data simultaneously using c# sockets
body: <p>I have a C# .net server &amp; client (TCP). The server listens for multiple clients in an asynchronous manner. The clients can send data ranging from screenshots, to messages, to a videostream (really just multiple screenshots sent extremely fast which never works...), to system information. The problem that I'm facing is that when all of these are possibilites, the server can only receive so little. I can't seem to download a file from a client &amp; receive a screenshot at the same time. Or when receiving multiple screenshots really fast to emulate screensharing, I can't download a file (this usually crashes the data receiving process.) </p>
  
  <p>I don't even think my server is correctly receiving data for clients, as data often is corrupt and throws exceptions. I'll start with my server listening code itself:</p>
  
  <pre><code>    public void Listen()
      {
          _socket.Listen(100);
          _socket.BeginAccept(new AsyncCallback(AcceptCallback), null);
          CSCLog("Server started || Listening...");
  
          void AcceptCallback(IAsyncResult AR)
          {
              Socket socket = _socket.EndAccept(AR);
  
              clienthandler client = new clienthandler(socket, _dash);
              _socketClientList.Add(client);
  
              // Repeat the listening process...
              _socket.BeginAccept(new AsyncCallback(AcceptCallback), null);
          }
      }
  </code></pre>
  
  <p>The server holds a custom class, clienthandler, that requires a socket and provides individual socket "control." Here is the basic run down of that class:</p>
  
  <pre><code>public class clienthandler
  {
      public Socket _clientSocket;
      public clienthandler(Socket paramSocket)
      {
          _clientSocket = paramSocket;
          receiveAll();
      }
  
      public void receiveAll()
      {
          int BUFF_SIZE = 4024 * 2;
          byte[] _lengthBuffer = new byte[BUFF_SIZE];
  
          _clientSocket.BeginReceive(_lengthBuffer, 0, _lengthBuffer.Length, 0, new AsyncCallback(LengthCallBack), _clientSocket);
  
          void LengthCallBack(IAsyncResult lengthAR)
          {
              try
              {
                  Socket buffSocket = (Socket)lengthAR.AsyncState;
                  int lengthreceived = _clientSocket.EndReceive(lengthAR);
                  byte[] lengthdata = new byte[lengthreceived];
                  Array.Copy(_lengthBuffer, lengthdata, lengthreceived);
  
                  // Handle the received incoming data length
                  DataInformation datai = (DataInformation)ObjectHandler.Deserialize(_lengthBuffer);
                  int datalength = datai.datalength;
  
                  Array.Clear(_lengthBuffer, 0, _lengthBuffer.Length);
  
                  PrepCol(datai, buffSocket);
  
                  // Repeat the data length listening process...
                  _clientSocket.BeginReceive(_lengthBuffer, 0, _lengthBuffer.Length, 0, new AsyncCallback(LengthCallBack), _clientSocket);
  
              }
              catch (Exception ex) { // handle exception... }
          }
      }
  }
  </code></pre>
  
  <p>To further explain, the <code>receiveAll()</code> function tries to asynchronously listen for data. I've created a custom class (these are all stored in a .DLL that the client and server share) called <code>DataInformation</code> that acts as a header for data being sent through the stream. It only includes an enum of an <code>objectType</code> &amp; <code>int datalength</code> that signifies the amount of incoming data my client sends right afterwards (as any data sent from the client has its own DataInformation sent first, then immediately after is the actual data. Both are serialized.)</p>
  
  <p>The <code>PropCol()</code> methods takes in the deserialized DataInformation class and socket object. It then collects data using the datainformation variables provided (the Enum &amp; int datalength.):</p>
  
  <pre><code>    public void PrepCol(DataInformation paramDatainformation, Socket paramBuffSocket)
      {
          int datalength = paramDatainformation.datalength;
  
          object streamobj;
          MemoryStream ms = new MemoryStream();
  
          if(paramDatainformation.objectType == ObjectType.Universal)
          {
              // Prepare &amp; collect the incoming data
              while (datalength &gt; 0)
              {
                  byte[] buffer;
                  if (datalength &lt; paramBuffSocket.ReceiveBufferSize)
                  {
                      buffer = new byte[datalength];
                  }
                  else
                      buffer = new byte[paramBuffSocket.ReceiveBufferSize];
  
                  int rec = paramBuffSocket.Receive(buffer, 0, buffer.Length, 0);
  
                  datalength -= rec;
                  ms.Write(buffer, 0, rec);
              }
  
              // Handle the collected data
              ms.Close();
              byte[] data = ms.ToArray(); ms.Dispose();
              streamobj = ObjectHandler.Deserialize(data);
              Array.Clear(data, 0, data.Length);
  
              // Check the data that is received &amp; determine type
              CheckData(streamobj);
          }
  
          if(paramDatainformation.objectType == ObjectType.Screenshot)
          { // Receive data certain way }
  
          if(paramDatainformation.objectType == ObjectType.TransferFile)
          { // Receive data certain way }
      }
  </code></pre>
  
  <p>It utilizes a <code>while</code> loop to synchronously receive data until it has received the amount that the DataInformation says it needs. It takes the data object and passes it into the <code>CheckData()</code> method that requires an object. It takes the object and checks if it is any object it can handle (such as a screenshot, or message, ect...), if so then it does.</p>
  
  <p>The problem I find the most is that when receiving large data, or data really fast, my DataInformation deseralization in the <code>receiveAll()</code> method returns corrupt/ invalid data which isn't good at all because I'm losing something that I could be needing. </p>
  
  <p>My question really boils down to <strong>what am I doing wrong?</strong> Or how should I take the approach to receive multiple data simultaneously?</p>
  
  <p>Any more information I could provide is that the Serialization &amp; Desserialization methods are in the .DLL. That's really all. I apologize for dumping large amounts of code out, but felt like those were the most relevent things. Thank you for your time.</p>