(分享)winsock 编程基础 之 就绪通告 I/O 模型
程序代码:
//*******************************就绪通告I/O模型************************************** //////////////////////////////////////////////////////////////////////////////////////////////////////// // **************select模型*************** // 一个线程只能等待一个I/O操作 // select能检测多个套接字上的多个操作 //int select( // int nfds, // fb_set *readfbs, fb_set为套接字句柄的集合 // fb_set *writefbs, // fb_set *exceptfbs, // const timeval *timeout); // SOCKET sasocket; // fb_set fbread; 定义一个读数据的套接字的集合变量 fb // fb_set fbwrite; 写 // fb_set fbexcept 异常 // FD_SET(sasokcet,&fbexcept) // FD_SET(sasocket,&fbread); 将sasocket装入fbread集合中 // // int err=0; // if(FD_ISSET(sasocket,&fbexcept)) fbexcep集合中sasocket是否发生异常 // { // int errlen=sizeof(err); // ****WSAGetLastError 针对当前线程********getsockopt针对一个具体的套接字****** // getsockopt(sasocket, // SOL_SOCKET, 选项定义的级别;仅支持的秩是 SOL_SOCKET 和 IPPROTO_TCP // SO_ERROR, 该值将检索的套接字选项 // (CHAR*)&err, 到所请求的选项的值将返回缓冲区的指针(返回值的地址) // 对于 SO_LINGER,这将是 LINGER 结构的大小 // 对于其他选项将是 BOOL 或 int的范围,具体取决于选项卡 // &errlen); 为 lpOptionValue 缓冲区的大小的指针(以字节为单位)。 // if(err==WSAEWOULDBLOCK) // **************************************************************************** /////////////////////////////////////////////////////////////////////////////////////////////////////////// // ******************WSAAsyncSelect模型****************** // int WSAAsyncSelect( // SOCKET s, // HWND hwnd, // UINT wMsg, 自定义消息 WM_USER+1 // LONG lEvent); 满足时通知线程 FD_CLOSE可以关闭 FD_ACCEPT FD_WRITE FD_READ // *****wParam 套接字句柄 //******* WSAGETSELECTERROR(lParam) 错误信息 //******* WSAGETSELECTEVENT(lParam) I/O操作信息 //当接到FD_WRITE消息后 会一直掉用send() 直到返回WSAEWOULDBLACK 即没有可用的发送缓冲区 //消息循环........... // *************************************************************************** /////////////////////////////////////////////////////////////////////////////////////////////////////////// // ********************WSAEventSelect模型********************* // int WSAEventSelect( *****将套接字句柄与事件关联**** // SOCKET s, // WSAEVENT hEventObject, // LONG lEvents); // WSAEVENT wsaEvent; // WSACreateEvent WSASetEvent WSAResetEvent // DWORD WSAWaitForMultipleEvents( ***WSA_MAXIMUM_WAIT_EVENTS**64** // DWORD cEvents, 等待的事件内核对象数组的大小 // const WSAEVENT FAR* lphEvents, 事件内核对象数组的首地址 // BOOL fWaitAll, // DWORD dwTimeout, WSA_INFINITE // BOOL fAlertable); //*******fWaitAll=FALSE时 返回值-WSA_WAIT_EVENT_0表示的是出现的信号的事件在lpEvents中的索引值 // 当有多个事件出现信号时, 表示的是最前面的 索引值最小的出现信号的事件 //***为避免“饿死”: 再次调用WSAWaitForMultipleEvents() 指定等待时间为0********** //WSAWaitForMultipleEvents错误则返回WSA_WAIT_FAILED // if(return != WSA_WAIT_FAILED) // { // int nEventIndex=return-WSA_WAIT_EVENT_0; // if(nEventIndex==0) ********处理单个套接字的单个I/O操作 // { // //处理其他事件 // ******WSAResetEvent(wsaEvent); *****没有自动重置***** // } // else // if(nEventIndex==1) // } ///////////////////////////////////////////////////////////////////////////////// // // int WSAEnumNetworkEvents( // SOCKET s, // WSAEVENT hEventObject, *******处理单个套接字的多个I/O操作 // LPWSANETWORKEVENTS lpNetworkEvents); // WSANETWORKEVENTS wsanetworkevents; // // strcut WSANETWORKEVENTS // { // long lNetworkEvents; 可操作的I/O信息 // int iErrorCode[FD_MAX_EVENTS]; // } // if(wsanetworkevents.lNetworkEvents & FD_READ) // { // //调用recv() ******会自动重置******* // } // if(wsanetworkevents.iErrorCode[FD_READ_BIT] !=0) // { // //错误,不能调用recv() // } //************************************************************************************************