'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 |
