'Asynchronous Socket chat crashes on BeginReceive

This is console chat application is based on asynchronous socket. It crashes during BeginReceive:

The error is "An established connection was aborted by the software in your host machine." The antivirus is not the problem.

This is where Receive() is called.

static void RunClient()
        {
            // Connect to a remote device.  
            try
            {
                // Connect to the remote endpoint.  
                client.BeginConnect(remoteEndPoint,
                                    new AsyncCallback(ConnectCallback),
                                    client);
                connectDone.WaitOne();

                while (client.Connected)
                {
                    try
                    {
                        Console.WriteLine("Input: ");
                        const string END_OF_FILE = "<EOF>";

                        string message = $"{Console.ReadLine()}{END_OF_FILE}";
                        Send(client, message);
                        sendDone.WaitOne();

                        // Receive the response from the remote device.  
                        Receive(client);
                        receiveDone.WaitOne();

                        // Write the response to the console.  
                        Console.WriteLine($"Response received : {response}");
                    }
                    catch (Exception exception)
                    {

                        Console.WriteLine(exception.ToString());
                    }
                }

                // Release the socket.  
                client.Shutdown(SocketShutdown.Both);
                client.Close();
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.ToString());
            }
        }

Edit: It works once, and then the error message shows.

Edit 2:

This is the Receive method.

private static void Receive(Socket client)
        {
            try
            {
                // Create the state object.  
                StateObjectClient state = new StateObjectClient();
                state.workSocket = client;

                // Begin receiving the data from the remote device.  
                client.BeginReceive(state.buffer,
                                    0,
                                    StateObjectClient.BUFFER_SIZE,
                                    0,
                                    new AsyncCallback(ReceiveCallback),
                                    state);
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.ToString());
            }
        }


Solution 1:[1]

I think your error is a fundamental misunderstanding of how TCP works.

TCP is a stream protocol, not a message protocol. The only gurantees for a TCP stream are

  • the bytes you send will be received in the same order they are sent
  • the bytes will be received only once

But you can send a message of 100 bytes and the other side can

  • receive a 100 byte chunk
  • 100 1 byte chunks
  • 2 50 byte chunks
  • ...

So you must keep looping till you have received everything. This is turn mean that you must know how big a message you expect. Either

  • always use the same size
  • prefix the message witha length of well known length (4 ascii bytes say)
  • or have a recognizable end of message

How to do this

I assume that 'respnse' contains a string of the last received block.

 StringBuilder msg = new StringBuilder();
 while(true){
           Receive(client);
           receiveDone.WaitOne();
           msg.Append(response);
           if(response.EndsWith(END_OF_FILE))
               break;
  }
  response = msg.ToString();

Not being able to see how you unpack the received bytes I hope the EndsWith is correct, maybe there is a newline of something tacked on te end

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1