title: Determine end of message in socket stream
body: <p>I have a project with a server and a client using asynchronous socket connections.</p>
  
  <p>I want to transmit an object from server to client. Unfortunately I have the problem, that sometimes the object isn't fully transmitted in one go. Therefore I need a way to determine when an object was fully transmitted. So I added a four-byte-head to the data transmitted to tell, how long the stream will be.</p>
  
  <pre><code>Server
  
  private void Send(Socket handler, Packet packet)
      {
          byte[] byteData = ByteHelper.Serialize(packet).Data;
  
          byte[] byteDataLength = BitConverter.GetBytes(byteData.Length);
  
          byte[] transmissionData = new byte[byteDataLength.Length + byteData.Length];
          byteDataLength.CopyTo(transmissionData, 0);
          byteData.CopyTo(transmissionData, byteDataLength.Length);
  
          if (debug)
          {
              Status = "Sending "+packet.Type+"-packet to client.";
          }
  
          try
          {
              handler.BeginSend(transmissionData, 0, transmissionData.Length, 0, new AsyncCallback(SendCallback), handler);
          }
          catch (Exception ex)
          {
              Status = "[EXCEPTION]" + ex.Message.ToString();
          }
      }
  </code></pre>
  
  <p>The client receives the stream and evaluates the first four bytes to create a StateObject which has the right size. But I have the feeling that this is not really a good way to solve my problem. Is there a better way to do this?</p>
  
  <pre><code>Client
  
  private void ReceiveCallback(IAsyncResult ar)
      {
          StateObject state = (StateObject)ar.AsyncState;
          try
          {
              Socket client = state.workSocket;
  
              int bytesRead = client.EndReceive(ar);
  
              if (bytesRead &gt; 0)
              {
                  do
                  {
                      state = AdjustState(state);
                      if (state != null)
                      {
                          if (state.buffer.Length == state.bufferSize)
                          {
                              ProcessPacket(state);
                              receiveDone.Set();
                          }
                      }
                      else
                      {
                          receiveDone.Set();
                      }
                  }
                  while (state != null &amp;&amp; state.tempBuffer.Length &gt;= state.bufferSize);
                  if (state != null)
                  {
                      client.BeginReceive(state.tempBuffer, 0, state.tempBuffer.Length, 0, new AsyncCallback(ReceiveCallback), state);
                  }
              }
          }
          catch (Exception ex)
          {
              MessageBox.Show("ReceiveCallback: " + ex.ToString(), "Client-Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
          }
      }
  
  private static StateObject AdjustState(StateObject state)
      {
          StateObject tempState = state;
          if (tempState.tempBuffer.Length &gt;= 4)
          {
              byte[] sizeBytes = tempState.tempBuffer.Take(4).ToArray();
              int bufferSize = BitConverter.ToInt32(sizeBytes, 0);
              if (bufferSize == 0)
              {
                  return null;
              }
              byte[] temp = tempState.tempBuffer.Skip(4).ToArray();
              Socket tempSocket = tempState.workSocket;
              tempState = new StateObject(bufferSize);
              tempState.BufferSet();
              if (temp.Length &gt;= bufferSize)
              {
                  tempState.buffer = temp.Take(bufferSize).ToArray();
                  tempState.tempBuffer = temp.Skip(bufferSize).ToArray();
              }
              tempState.workSocket = tempSocket;
          }
          return tempState;
      }
  </code></pre>
  
  <p><strong>Solution</strong></p>
  
  <p>Thanks to <strong>usr</strong> I've changed the bytesRead-Part in the ReceiveCallbackCode of the client to this. It seems to work now.</p>
  
  <pre><code>if (bytesRead &gt; 0)
              {
                  if (!state.bufferSet)
                  {
                      state = AdjustState(state);
                      client.BeginReceive(state.buffer, 0, state.bufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                  }
                  else
                  {
                      if (state.buffer.Length == state.bufferSize)
                      {
                          ProcessPacket(state);
                          receiveDone.Set();
                      }
                      else
                      {
                          client.BeginReceive(state.buffer, state.buffer.Length, state.bufferSize - state.buffer.Length, 0, new AsyncCallback(ReceiveCallback), state);
                      }
                  }
              }
  </code></pre>