【转】WSAEVENTSELECT模型-简述

来源:互联网 发布:淘宝查号截图是什么 编辑:程序博客网 时间:2024/06/13 02:41

WSAEVENTSELECT模型-简述

 http://www.hudong.com/wiki/WSAEVENTSELECT模型

确定与所提供的FD_XXX网络事件集合相关的一个事件对象。
  #include 
  int WSAAPI WSAEventSelect ( SOCKET s, WSAEVENT
  hEventObject, long lNetworkEvents );
  s:一个标识套接口的描述字。
  hEventObject:一个句柄,用于标识与所提供的FD_XXX网络事件集合相关的一个事件对象。
  lNetworkEvents:一个屏蔽位,用于指定感兴趣的FD_XXX网络事件组合。
  返回值:
  如果应用程序指定的网络事件及其相应的事件对象成功设置,则返回0。否则的话,将返回INVALID_SOCKET错误,应用程序可通过WSAGetLastError()来获取相应的错误代码。
  在使用select()和WSAAsyncSelect()函数时,WSAEventSelect()常用来决定何时进行数据传送操作(如send()或recv()),并期望能立即成功。但是一个稳定的应用程序应该做好这样的准备,即事件对象被设置,并且一个WinSock调用以WSAEWOULDBLOCK立即返回 。举例来说,有可能发生下述操作序列:
  (i) 套接口s上到达数据;WinSock设置了WSAEventSelect事件对象。
  (ii) 应用程序进行其他操作。
  (iii) 在进行操作时,应用程序调用了ioctlsocket(s, FIONREAD...)并发现有数据可读。
  (iv) 应用程序调用一个recv(s,...)来读取数据。
  (v) 最后应用程序等待WSAEventSelect()所指定的数据对象,该数据对象指出数据可读。
  (vi) 应用程序调用recv(s,...),但以WSAEWOULDBLOCK错误失败。
  其他的操作序列也是可能的。
  成功地记录了网络事件的发生(通过设置内部网络事件记录的相应位),并且将相应的事件对象设置了信号后,不会对该网络事件作进一步的操作,直到应用程序调用了相应的函数显式地重新允许该网络事件及相应事件对象的信号。
  网络事件                                        重新允许函数
  FD_READ                                recv() 或 recvfrom()
  FD_WRITE                                send() 或 sendto()
  FD_OOB                                        recv()
  FD_ACCEPT                                accept() 或WSAAccept(),直到返回的错误代码为 WSATRY_AGAIN,指明条件函数返回CF_DEFER。
  FD_CONNECT                        NONE
  FD_CLOSE                                NONE
  FD_QOS                                        用SIO_GET_QOS 命令调用WSAIoctl()。
  FD_GROUP_QOS                        用SIO_GET_GROUP_QOS命令调用WSAIoctl()。
  错误代码:
  WSANOTINITIALISED                在调用本API之前应成功调用WSAStartup()。
  WSAENETDOWN                        网络子系统失效。
  WSAEINVAL                                参数中有非法值,或者指定的套接口处于非法状态。
  WSAEINPROGRESS                一个阻塞的WinSock调用正在进行中,或者服务提供者仍在处理一个回调函数
  WSAENOTSOCK                        描述字不是一个套接口。
另请参阅:WSACloseEvent() ,WSACreateEvent(),WSAEnumNetworkEvents(),WSAGetOverlappedResult(),WSAWaitForMultipleEvents().


它允许程序在一个套接字上接收以事件为基础的网络事件通知。
事件对象
       该模型要求程序对打算使用的每个套接字首先创建一个事件对象,方法是调用WSACreateEvent函数
WSAEVENT WSACreateEvent( void );
该函数返回创建好的事件对象。
        事件对象创建好后,必须将其与某个套接字关联在一起,同时注册感兴趣的网络事件类型。需调用WSAEventSelect函数。
int WSAEventSelect(
    SOCKET    sock,   /* 套接字 */
    WSAEVENT hEvent,   /* 事件对象 */
    long   lNetworkEvents /* 对应一个"位掩码",指定感兴趣的网络事件类型 */ 
    );
创建的事件拥有两种工作状态和两种模式。
工作状态 : 已传信和未传信
工作模式 : 人工重设和自动重设
由WSACreateEvent创建的事件对象,默认工作状态为"未传信",工作模式为"人工重设",当网络事件触发了与套接字关联在一起的事件对象时,工作状态会转变为"已传信",而在完成了一个I/O请求的处理之后,因为工作模式为"人工重设",因此,程序需要将工作状态从"已传信"改变为"未传信",使用WSAResetEvent函数
BOOL WSAResetEvent( WSAEVENT hEvent );
当程序不在对事件对象进行处理时,应调用WSACloseEvent函数将其关闭
BOOL WSACloseEvent( WSAEVENT hEvent );
套接字与事件对象关联在一起后,便可开始进行I/O操作,方法是等待一个或多个事件对象,并在事先指定的一个或所有句柄进入"已传信"状态,或在超过了一个规定的时间间隔后,立即返回。使用WSAWaitForMultipleEvents函数
DWORD WSAWaitForMultipleEvents(
   DWORD cEvents,   /* 指定lphEvents的数量,最大为WSA_MAXIMUM_WAIT_EVENTS(64) */
   const WSAEVENT *lphEvents, /* 事件对象数组 */ 
   BOOL fWaitAll,
   DWORD dwTimeout,   /* 等待时间,为0,立即返回,为WSA_INFINITE,永不返回 */
   BOOL fAlertable   /* 可设为FALSE */
     );
fWaitAll : 指定如何等待lphEvents数组内的事件对象,为TRUE时,只有当所有事件对象都进入"已传信"时,才会返回,若为FALSE时,只要一个事件进入"已传信"状态,就返回,通常设为FALSE
返回值:返回发生网络事件的事件对象索引
当发生网络事件后,接下来可调用WSAEnumNetworkEvents函数来检查发生了什么类型的网络事件
int WSAEnumNetworkEvents(
   SOCKET sock,
   WSAEVENT hEvent,
   LPWSANETWORKEVENTS lpNetworkEvents
    );
lpNetworkEvents : 为一个结构,内包含发生的事件及可能的错误代码
typedef struct _WSANETWORKEVENTS
{
long lNetworkEvents;    /* 发生的网络事件 */
int iErrorCode[FD_MAX_EVENTS]; /* 可能的错误代码 */
}WSANETWORKEVENTS,*LPWSANETWORKEVENTS;
iErrorCode : 指定错误代码数组,其索引名为事件类型名+'_BIT'(如FD_READ_BIT)