CSocket如何从CAsyncSocket变成同步

CSocket是MFC在CAsyncSocket基础上派生的一个同步阻塞Socket的封装类。它是如何又把CAsyncSocket变成同步的,而且还能响应同样的Socket事件呢?
  其 实很简单,CSocket在Connect()返回WSAEWOULDBLOCK错误时,不是在OnConnect(),OnReceive()这些事件 终端函数里去等待。你先必须明白Socket事件是如何到达这些事件函数里的。这些事件处理函数是靠CSocketWnd窗口对象回调的,而窗口对象收到 来自Socket的事件,又是靠线程消息队列分发过来的。总之,Socket事件首先是作为一个消息发给CSocketWnd窗口对象,这个消息肯定需要 经过线程消息队列的分发,最终CSocketWnd窗口对象收到这些消息就调用相应的回调函数(OnConnect()等)。
   所以,CSocket在调用Connect()之后,如果返回一个WSAEWOULDBLOCK错误时,它马上进入一个消息循环,就是从当前线程的消息队 列里取关心的消息,如果取到了WM_PAINT消息,则刷新窗口,如果取到的是Socket发来的消息,则根据Socket是否有操作错误码,调用相应的 回调函数(OnConnect()等)。
  大致的简化代码为:

  BOOL CSocket::Connect( ... )
  {
   if( !CAsyncSocket::Connect( ... ) )
   {
    if( WSAGetLastError() == WSAEWOULDBLOCK ) file://由 于异步操作需要时间,不能立即完成,所以Socket返回这个错误
    {
     file://进 入消息循环,以从线程消息队列里查看FD_CONNECT消息,直到收到FD_CONNECT消息,认为连接成功。
     while( PumpMessages( FD_CONNECT ) );
    }
   }
  }
  BOOL CSocket::PumpMessages( UINT uEvent )
  {
      CWinThread* pThread = AfxGetThread();
      while( bBlocking ) file://bBlocking 仅仅是一个标志,看用户是否取消对Connect()的调用
      {
          MSG msg;
          if( PeekMessage( &msg, WM_SOCKET_NOTIFY ) )
          {
             if( msg.message == WM_SOCKET_NOTIFY && WSAGETSELECTEVENT(msg.lParam) == uStopFlag )
             {
                 CAsyncSocket::DoCallBack( msg.wParam, msg.lParam );
                 return TRUE;
             }     
         }
         else
        {
             OnMessagePending(); file://处 理消息队列里的其它消息
             pThread->OnIdle(-1);
        }
     }
  }
  BOOL CSocket::OnMessagePending()
  {
      MSG msg;
       if( PeekMessage( &msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE ) )
       { file://这 里仅关心WM_PAINT消息,以处理阻塞期间的主窗口重画
           ::DispatchMessage( &msg );
           return FALSE;
       }
       return FALSE;
  }

   其它的CSocket函数,诸如Send(),Receive(),Accept()都在收到WSAEWOULDBLOCK错误时,进入 PumpMessages()消息循环,这样一个原本异步的CAsyncSocket,到了派生类CSocket,就变成同步的了。
  明白之后,我们可以对CSocket应用自如了。比如有些程序员将CSocket的操作放入一个线程,以实现多线程的异步Socket(通常,同步+多线程 相似于 异步 )。

 

本文来自于:http://www.chinaitpower.com/A/2001-10-12/1450.html

你可能感兴趣的:(多线程,socket,File,null,mfc,终端)