Reputation: 5627
My socket client does not appear to be handling situations where the buffer is full and there is more data to be received.
Here is my on receive method, simple version:
private void Recieve()
{
this._clientSocket.BeginReceive(this._buffer, 0, this._buffer.Length, 0,
new AsyncCallback(OnReceive), this._clientSocket);
}
private void OnReceive(IAsyncResult result)
{
Socket clientSocket = (Socket)result.AsyncState;
int bytesRead = clientSocket.EndReceive(result);
this.Recieve();
string data = Encoding.ASCII.GetString(this._buffer, 0, bytesRead);
ThreadPool.QueueUserWorkItem(new WaitCallback(this.HandleDataReceived), data);
}
This doesn't handle situations where there is more data to be received at all. So then I tried this (http://msdn.microsoft.com/en-us/library/bew39x2a.aspx):
private string receivedString = string.Empty;
private void OnReceive(IAsyncResult result)
{
Socket clientSocket = (Socket)result.AsyncState;
int bytesRead = clientSocket.EndReceive(result);
if (bytesRead > 0)
{
receivedString += Encoding.ASCII.GetString(this._buffer, 0, bytesRead);
this.Recieve();
}
else
{
ThreadPool.QueueUserWorkItem(new WaitCallback(this.HandleDataReceived), this.receivedString);
this.receivedString = string.Empty;
}
}
But the problem i'm having with this is that when bytesRead > 0 and I call BeginReceive again I do not get another callback. Did I make some kind of mistake ?
Thanks
Upvotes: 0
Views: 453
Reputation: 133950
In the first code, you have a race condition. Consider:
private void OnReceive(IAsyncResult result)
{
Socket clientSocket = (Socket)result.AsyncState;
int bytesRead = clientSocket.EndReceive(result);
this.Recieve();
string data = Encoding.ASCII.GetString(this._buffer, 0, bytesRead);
ThreadPool.QueueUserWorkItem(new WaitCallback(this.HandleDataReceived), data);
}
You call Receive
again, which could overwrite buffer
before you send the data to your HandleDataReceived
method. I think you want to move that Receive call to after you've converted the data:
private void OnReceive(IAsyncResult result)
{
Socket clientSocket = (Socket)result.AsyncState;
int bytesRead = clientSocket.EndReceive(result);
string data = Encoding.ASCII.GetString(this._buffer, 0, bytesRead);
ThreadPool.QueueUserWorkItem(new WaitCallback(this.HandleDataReceived), data);
this.Recieve();
}
In the second case, you never read 0 bytes because the socket is waiting for data. If there is no data, Socket.Receive will block until there is data available, or until the connection is closed. BeginReceive
is waiting for data.
Upvotes: 2