谁能告诉我C#中的Socket的BeginReceive内部是如何异步的?
我看了Socket源代码,但是不是很了解它的原理,它是就调用了WSARecv这个函数然后我不知道它是什么时候进行回调的,它是用WSAEventSelect?
public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
{
if (CleanedUp) {
throw new ObjectDisposedException(this.GetType().FullName);
}
//
// parameter validation
//
if (buffer==null) {
throw new ArgumentNullException("buffer");
}
if (offset<0 || offset>buffer.Length) {
throw new ArgumentOutOfRangeException("offset");
}
if (size<0 || size>buffer.Length-offset) {
throw new ArgumentOutOfRangeException("size");
}
// We need to flow the context here. But we don't need to lock the context - we don't use it until the callback.
OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
asyncResult.StartPostingAsyncOp(false);
// Run the receive with this asyncResult.
errorCode = DoBeginReceive(buffer, offset, size, socketFlags, asyncResult);
if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
asyncResult = null;
}
else
{
// We're not throwing, so finish the async op posting code so we can return to the user.
// If the operation already finished, the callback will be called from here.
asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
}
if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginReceive", asyncResult);
return asyncResult;
}
private SocketError DoBeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
{
GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceive() size:" + size.ToString());
#if DEBUG
IntPtr lastHandle = m_Handle.DangerousGetHandle();
#endif
// Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
// avoid a Socket leak in case of error.
SocketError errorCode = SocketError.SocketError;
try
{
// Set up asyncResult for overlapped WSARecv.
// This call will use completion ports on WinNT and Overlapped IO on Win9x.
asyncResult.SetUnmanagedStructures(buffer, offset, size, null, false /* don't pin null RemoteEP*/, ref Caches.ReceiveOverlappedCache);
// This can throw ObjectDisposedException.
int bytesTransferred;
errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecv(
m_Handle,
ref asyncResult.m_SingleBuffer,
1,