标签:
winsock编程WSAEventSelect模型WSAEventSelect模型和WSAAsyncSelec模型类似,都是用调用WSAXXXXXSelec函数将socket和事件关联并注册到系统,并将socket设置成非阻塞模式。二者不同之处在于socket事件的通知方法:WSAAsyncSelec模型利用窗口句柄和消息映射函数通知网络事件,而WSAEventSelect模型利用WSAEVENT通知网络事件。完成WSAEventSelect模型需要涉及以下函数或结构:
1:WSAEventSelectDescription:The WSAEventSelect function specifies an event object to be associated with the specified set of FD_XXX network events.
1 int WSAEventSelect( 2 __in SOCKET s, 3 __in WSAEVENT hEventObject, 4 __in long lNetworkEvents 5 );
Parameters
sDescriptor identifying the socket.
hEventObjectHandle identifying the event object to be associated with the specified set of FD_XXX network events.与socket关联的事件对象,同时需要指定事件对象的类型,lNetworkEvents
lNetworkEventsBitmask that specifies the combination of FD_XXX network events in which the application has interest.
事件对象的事件集合,FD_ACCEPT等,用|符号指定多个类型。在WSAAsyncSelec相关文章内有介绍。
Return Value
The return value is zero if the application‘s specification of the network events and the associated event object was successful. Otherwise, the value SOCKET_ERROR is returned, and a specific error number can be retrieved by calling WSAGetLastError.
RemarksThe WSAEventSelect function automatically sets socket s to nonblocking mode, regardless of the value of lNetworkEvents. To set socket s back to blocking mode, it is first necessary to clear the event record associated with socket s via a call to WSAEventSelect with lNetworkEvents set to zero and the hEventObject parameter set to NULL. You can then call ioctlsocket or WSAIoctl to set the socket back to blocking mode.
不管第3个参数是什么,WSAEventSelect 都会设置socket为非阻塞模式。设置socket为阻塞模式,受限需要清除socket的事件和事件类型关联,即再次调用WSAEventSelect ,将hEventObject 赋值为NULL,将lNetworkEvents 赋值为0。然后,调用ioctlsocket设置socket为阻塞模式。
rc = WSAEventSelect(s, hEventObject, 0);
上例中,事件集合被设置为0,这将取消socket与事件的关联。MSDN给出解释,第三个参数为0,事件句柄hEventObject将被忽略。
对同一个socket调用两次WSAEventSelect ,第二次传入的参数将覆盖第一次传入参数的效果。
1 rc = WSAEventSelect(s, hEventObject1, FD_READ); 2 rc = WSAEventSelect(s, hEventObject2, FD_WRITE); //bad
上例中,s将只接收FD_WRITE事件消息。如果想要FD_WRITE和FD_READ都生效,需要改成FD_WRITE|FD_READ。
Issuing a WSAAsyncSelect for a socket cancels any previous WSAAsyncSelect or WSAEventSelect for the same socket。
Issuing a WSAEventSelect for a socket cancels any previous WSAAsyncSelect or WSAEventSelect for the same socket and clears the internal network event record.
WSAAsyncSelect 和WSAEventSelect 能够互相取消对方的网络事件状态,所以,一个网络事件event,不可能同时被WSAAsyncSelect 和WSAEventSelect 触发,必有一个永远无法的到消息。也就是说,最好不要同时使用WSAAsyncSelect 和WSAEventSelect ,以免线程无限期等待。
2:WSAEVENT、WSACreateEvent、WSACloseEvent、WSASetEvent、WSAResetEvent和windows的event对象一样,WSAEVENT实际类型是HANDLE。WSACreateEvent和WSACloseEvent分别用了创建WSAEVENT和销毁WSAEVENT。函数定义如:
2.1 WSACreateEventWSAEVENT WSACreateEvent(void);
Return ValueIf no error occurs, WSACreateEvent returns the handle of the event object. Otherwise, the return value is WSA_INVALID_EVENT. To get extended error information, call WSAGetLastError.
RemarksThe WSACreateEvent function creates an event object that is manually reset with an initial state of nonsignaled. Windows Sockets 2 event objects are system objects in Windows environments. Therefore, if a Windows application desires auto reset events, it can call the native CreateEvent Windows function directly. The scope of an event object is limited to the process in which it is created.