Search code examples
c#.nettcptcpclient

TcpClient doesn't reveive all data


I have a "messenger" application that works like this: Client Sends Message to Server -> Server forwards Message to rest of the clients -> Clients read the message.

The server always receives the messages, but the clients do not.

Code that forwards the message to all clients (Server/TcpListener):

public static void SendToAll(TcpClient sender, string message)
{
   // Log the recieved message in the console
   Console.WriteLine(message);

   // Save the recieved message for new clients
   messageLog += message + "\n";

   byte[] msg = Encoding.ASCII.GetBytes(message);
   foreach (TcpClient client in clients.Keys)
   {
      if (client == sender || clients[client] == "") continue;
      if (!client.Connected)
      {
         clients.Remove(client);
         continue;

      }

      NetworkStream stream = client.GetStream();
      stream.Write(msg, 0, msg.Length);
   }
}

Code that reads messages from the server (TcpClient):

byte[] buffer = new byte[1024];
while (true)
{
   using (MemoryStream memoryStream = new MemoryStream())
   {
      Int32 bytes = 0;
      do
      {
         bytes = stream.Read(buffer, 0, buffer.Length);
         memoryStream.Write(buffer, 0, bytes);
      }
      while (stream.DataAvailable);
      Console.WriteLine(Encoding.ASCII.GetString(memoryStream.ToArray()));
}

Server (image attached)

Client1 (image attached)

Client2 (image attached)


Solution

  • Found the answer.

    The problem was probably caused because TCP is slow; not entirely finished with reading all the stream and already tasked with reading new data.

    So I Switched

    byte[] buffer = new byte[1024];
    while (true)
    {
       using (MemoryStream memoryStream = new MemoryStream())
       {
          Int32 bytes = 0;
          do
          {
             bytes = stream.Read(buffer, 0, buffer.Length);
             memoryStream.Write(buffer, 0, bytes);
          }
          while (stream.DataAvailable);
          Console.WriteLine(Encoding.ASCII.GetString(memoryStream.ToArray()));
    }
    

    to

    // ... Main() {
    while (true) StartRead();
    // ... }
    
    public static async void StartRead(NetworkStream stream)
    {
        byte[] buffer = new byte[1024];
        Int32 bytesRead = await stream.ReadAsync(buffer.AsMemory(0, buffer.Length));
        string message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
        Console.WriteLine(message);         
    }