更新时间:2023-12-24 10:39
非阻塞模式是指利用socket事件的消息机制,Server端与Client端之间的通信处于异步状态。
在非阻塞模式下利用socket事件的消息机制,Server端与Client端之间的通信处于异步状态下。通常需要从CSocket类派生一个新类,派生新类的目的是重载socket事件的消息函数,然后在socket事件的消息函数中添入合适的代码以完成Client端与Server端之间的通信,与阻塞模式相比,非阻塞模式无需创建一个新线程。
这里将讨论当Server端socket事件-FD_ACCEPT被触发后,该事件的处理函数OnAccept是如何进一步被触发的。其它事件的处理函数如OnConnect,OnReceive等的触发方式与此类似。在1中已提到Client/Server端通信时,Server端socket正在接收来自Client端socket连接请求,这将会触发FD_ACCEPT事件,同时Server端的网络传输服务进程向Server端的socketwindow(CSocketWnd)发送事件通知消息WM_SOCKET_NOTIFY,通知有FD_ACCEPT事件产生,CsocketWnd在收到事件通知消息后,调用消息处理函数OnSocketNotify:
LRESULTCSocketWnd::OnSocketNotify(WPARAMwParam,LPARAMlParam)
{
CSocket::AuxQueueAdd(WM_SOCKET_NOTIFY,wParam,lParam);
CSocket::ProcessAuxQueue();
return0L;
}
消息参数wParam是socket的句柄,lParam是socket事件。这里稍作解释一下,CSocketWnd类是作为CSocket类的友元类,这意味着它可以访问CSocket类中的保护和私有成员函数和变量,AuxQueueAdd和ProcessAuxQueue是CSocket类的静态成员函数,如果你对友元不熟悉,请迅速找本有关C 书看一下友元的使用方法吧!
ProcessAuxQueue是实质处理socket事件的函数,在该函数中有这样一句代码:
CAsyncSocket*pSocket=CAsyncSocket::LookupHandle((SOCKET)wParam,TRUE);
其实也就是由socket句柄得到发送事件通知消息的socket指针pSocket:从m_pmapSocketHandle中查找(见1)!
最后,WSAGETSELECTEVENT(lParam)会取出事件类型,在一个简单的switch语句中判断事件类型并调用事件处理函数。在这里,事件类型是FD_ACCEPT,当然就调用pSocket->OnAccept!
Server端socket处于阻塞调用模式下,它必须在一个新创建的线程中工作,防止主线程被阻塞。
当有多个Client端socket与Server端socket连接及通信时,Server端采用阻塞模式就显得不适合了,应该采用非阻塞模式,利用socket事件的消息机制来接受多个Client端socket的连接请求并进行通信。
在非阻塞模式下,利用CSocketWnd作为所有sockets的消息池,是实现socket事件的消息机制的关键技术。
当前模块状态——用于保存当前线程和模块状态的一个结构,可以通过AfxGetThreadModule()获得。AFX_MODULE_THREAD_STATE在CSocket重新定义为_AFX_SOCK_THREAD_STATE。
socket类型——在TCP/IP协议中,Client/Server网络程序采用TCP协议:即socket类型为SOCK_STREAM,它是可靠的连接方式。在这里不采用UDP协议:即socket类型为SOCK_DGRAM,它是不可靠的连接方式。