private void ProcessReceive(SocketAsyncEventArgs socketArgs)
{
if (socketArgs != _receiveSocketArgs)
throw new Exception("Invalid socket args received");
Interlocked.Increment(ref _recvAsyncCallbacks);
// socket closed normally or some error occured
if (socketArgs.BytesTransferred == 0 || socketArgs.SocketError != SocketError.Success)
{
NotifyReceiveCompleted(0);
ReturnReceivingSocketArgs();
CloseInternal(socketArgs.SocketError);
return;
}
NotifyReceiveCompleted((uint) socketArgs.BytesTransferred);
var receivedPackages = Interlocked.Increment(ref _packagesReceived);
var receivedBytes = Interlocked.Add(ref _bytesReceived, socketArgs.BytesTransferred);
//Console.WriteLine(String.Format("{0:mmss.fff}", DateTime.Now) + " received " + socketArgs.BytesTransferred + " bytes.");
// OK, so what does this line of code do? It makes an ArraySegment<byte> representing the data
// that we actually read.
// Then it constructs a little array to meet the IEnumerable interface.
// Then it makes original buffer (ArraySegment<byte>) we used for receive operation.
// Then it builds an IEnumerable that will dispose of our buffer (returning it to the buffer pool)
// later (as in later when some other thread (but it may be on this thread, we aren't sure) processes
// this buffer).
// This should be benchmarked vs copying the byte array every time into a new byte array
var receiveBufferSegment =
new ArraySegment<byte>(socketArgs.Buffer, socketArgs.Offset, socketArgs.BytesTransferred);
lock (_receivingLock)
{
var fullBuffer = new ArraySegment<byte>(socketArgs.Buffer, socketArgs.Offset, socketArgs.Count);
_receiveQueue.Enqueue(receiveBufferSegment);
}
lock (_receiveSocketArgs) {
if (socketArgs.Buffer == null)
throw new Exception("Cleaning already null buffer");
socketArgs.SetBuffer(null, 0, 0);
}
StartReceive();
TryDequeueReceivedData();
}