我看了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, 
                    out bytesTransferred,
                    ref socketFlags,
                    asyncResult.OverlappedHandle,
                    IntPtr.Zero);                 if (errorCode!=SocketError.Success) { 
                    errorCode = (SocketError)Marshal.GetLastWin32Error(); 
                    GlobalLog.Assert(errorCode != SocketError.Success, "Socket#{0}::DoBeginReceive()|GetLastWin32Error() returned zero.", ValidationHelper.HashString(this));
                } 
                GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceive() UnsafeNclNativeMethods.OSSOCK.WSARecv returns:" + errorCode.ToString() + " bytesTransferred:" + bytesTransferred.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
            }
            finally
            { 
                errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
            } 
 
            //
            // if the asynchronous native call fails synchronously 
            // we'll throw a SocketException
            //
            if (errorCode != SocketError.Success)
            { 
                //
                // update our internal state after this socket error and throw 
                asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache); 
                UpdateStatusAfterSocketError(errorCode);
                if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginReceive", new SocketException(errorCode)); 
                asyncResult.InvokeCallback(new SocketException(errorCode));
            }
#if DEBUG
            else 
            {
                m_LastReceiveHandle = lastHandle; 
                m_LastReceiveThread = Thread.CurrentThread.ManagedThreadId; 
                m_LastReceiveTick = Environment.TickCount;
            } 
#endif            return errorCode;
        } 

解决方案 »

  1.   

    看不清楚代码呢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, 
                        out bytesTransferred, 
                        ref socketFlags, 
                        asyncResult.OverlappedHandle, 
                        IntPtr.Zero);                 if (errorCode!=SocketError.Success) { 
                        errorCode = (SocketError)Marshal.GetLastWin32Error(); 
                        GlobalLog.Assert(errorCode != SocketError.Success, "Socket#{0}::DoBeginReceive()|GetLastWin32Error() returned zero.", ValidationHelper.HashString(this)); 
                    } 
                    GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceive() UnsafeNclNativeMethods.OSSOCK.WSARecv returns:" + errorCode.ToString() + " bytesTransferred:" + bytesTransferred.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult)); 
                } 
                finally 
                { 
                    errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode); 
                }             // 
                // if the asynchronous native call fails synchronously 
                // we'll throw a SocketException 
                // 
                if (errorCode != SocketError.Success) 
                { 
                    // 
                    // update our internal state after this socket error and throw 
                    asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache); 
                    UpdateStatusAfterSocketError(errorCode); 
                    if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginReceive", new SocketException(errorCode)); 
                    asyncResult.InvokeCallback(new SocketException(errorCode)); 
                } 
    #if DEBUG 
                else 
                { 
                    m_LastReceiveHandle = lastHandle; 
                    m_LastReceiveThread = Thread.CurrentThread.ManagedThreadId; 
                    m_LastReceiveTick = Environment.TickCount; 
                } 
    #endif             return errorCode; 
            } 
      

  2.   

    是同步和异步的切换,因为他有send和beginSend之类的可以同时使用