总结

来源:互联网 发布:淘宝虾米vip兑换码在哪 编辑:程序博客网 时间:2024/06/10 20:22
select模型
   
   select(
    int nfds;
fd_set fdread,
fd_set fdWrite,
fd_set fdException,
timeval time
   )
    FD_ZERO(*set) 将set初始化成空集合,集合在使用前都要清空
FD_CLR(s,*set) 从set中删除套接字S
FD_ISET(s,*set) 检查s是否为set集合
FD_SET(s,*set) 将套接字s加入set集合
select的优势是在单个线程中处理多个套接字,但是最大限制是64,由
FD_SETSIZE 定义,若要重新定义则需要在winsock2.h前定义.
     
 
WSAAsyncSelect 异步模型,提供异步通知,但是不提供异步数据传送
异步消息通知,自动置为非阻塞.
   int WSAAsyncSelect(
   SOCKET s,    // 套接字
   HWND hwnd,    // 窗口句柄
   unsigned int wMsg, // 自定义消息,标识发生了网络事件
   long lEvent,  // 要监听的事件,如果是0,则代表着清除网络事件
   )
   closesocket也可以清除套接字上的事件
   
   对于消息中的 wParam : 表示套接字
   对于消息中的 lParam :低位字表示网络事件
                         高字代表着可能出现的错误代码
  这里可以用WSAGETSELECTERROR获得高字位包含的错误信息
  我们可以用WSAGETSELECTEVENT获得发生了哪些事件
   一般是先调用WSAGETSELECTERROR,检查错误,如果没有错误再
   查看发生了什么事件.
   
   
   


事件模型
WSAEventSelect模型,提供异步通知,但是不提供异步数据传送
 
    1. WSAEVENT WSACreateEvent(void);
  其返回值是人工重设的事件句柄
2. int WSAEventSelect(
  SOCKET s.
  WSAEVENT hEventObject,
  long LNetWorkEvents,//感兴趣的事件
  );
  该步骤将事件句柄和套接字关联起来
才创建完毕时未传信状态,且是人工重设


WSAResetEvent(hEvent)重置信号状态,即变为未传信状态


WSACloseEvent(hEvent)关闭时间句柄




检测事件发生的函数
   DWORD WSAWaitForMultipleEvents(
   DWORD CEvent,  // 时间句柄数量
   const WSAEVENT FAR* lpEvents,  // 要监听的事件句柄集合
   DWORD fWaitAll, //是否等待全部事件句柄都有信号,才返回,false表示只要有信号传递,就返回
   DWORD dwTimeout,
   )
   
   当调用返回时,返回的是发生了的信号在lpEvents中的位置.
   
   这个时候就可以调用WSAEbumNetworkEvents(...) 函数枚举网络事件类型,
   并且还有将指定事件句柄重置为未传信的功能.
   WSAEnumNetworkEvents(
    SOCKET s,
WSAEVENT hEventObject,
LPWSANETWORKEVENTS lpNetworkEvents
   )   ;
   也可以使用wsaresetevent复位
   
   typedef struct _WSANETWORKEVENT
   {
     long lNetorkEvents;   // 网络事件类型
int i ErrorCode[FD_MAX_EVENT]; // 错误码
   }
   一个传信状态的事件句柄,可能发生多个网络事件
   
   example:
     if(NetworkEvents.lNetorkEvents & FD_READ)
{
   if(NetworkEvents.iErrorCode[FD_READ_BIT] != 0)
{
  // 发生了错误
}
}





重叠模型 (Overlapped IO)




typedef struct _WSAOVERLAPPED {
  DWORD        Internal;
  DWORD        InternalHigh;
  DWORD        Offset;
  DWORD        OffsetHigh;
  WSAEVENT     hEvent;
} WSAOVERLAPPED, *LPWSAOVERLAPPED;
其中,只需要设置事件句柄就可以了
其余的由系统帮助设定,
然后调用事件模型上的函数就可以判断了发生了哪些事件
最后调用WSAGetOverlappedResult(
 SOCKET s,   // 与重叠操作相对应的套接字
 LPWSAOVERLAPPED lpOverlapped, // 与套接字相对应的重叠结构体
 LPDWORD[out] lpcbTransfer,  // 返回实际读或者写的字节
 BOOL fWait,  // 是否等待操作完成
 LPDWORD lpdwFlags  // 标志着错误.
);
  BOOL WSAAPI WSAGetOverlappedResult(
  _In_  SOCKET          s,
  _In_  LPWSAOVERLAPPED lpOverlapped,
  _Out_ LPDWORD         lpcbTransfer,
  _In_  BOOL            fWait,
  _Out_ LPDWORD         lpdwFlags
);
   
完成例程
   该模型时另一种管理重叠IO的模型,一个完成历程必须得拥有下述函数
原形
   void CALLBACK CompletionROUTINE(
     DWORD dwError,  //表名一个重叠操作的完成状态是什么
DWORD cbTransferred, // 表名了在重叠操作期间,实际传输的字节量是多大
LPWSAOVERLAPPED lpOverlapped, // 表名了当初出啊你的WSAOVERLAPPED结构
DWORD dwFlags // 表明发挥操作结束时可能用的标志(如从WSARecv)
   );   
   
   
   首先在使用这种模型之前,需要创建一个完成端口
   
   HANDLE CreateIoCompletionPort
   (
     HANDLE FileHandle,
HANDLE ExistingCompletionPort,
DWORD CompletionKey,
DWORD NumberOfConcurrentThreads  // 该完成端口上运行执行的线程数量,为0时则告诉处理器,有多少个处理器就运行多少个线程
 
   );
   
   eg: CompletionPort = CreateIoCompletionPort(
   
   INVALID_HANDLE_VALUE,
   NULL,
   0,0
   );
   
   
   
   
   
 


    
   
0 0
原创粉丝点击