WinSock IO模型 实例
2014-03-24 22:19
393 查看
WSAEventSelect模型事件触发条件说明
1. FD_READ事件
调用WSAEventSelect函数时,如果当前有数据可读
有数据到达时,并且没有发送过FD_READ事件
调用recv/recvfrom函数后,仍然有数据可读时
2. RD_WRITE事件
调用WSAEventSelect函数时,如果调用能够发送数据时
调用connect()/accept()后,连接已经建立时
调用send()/sendto()函数后,返回WSAEWOULDBLOCK错误后,再次调用send()/sendto()函数可能成功时
3. FD_ACCEPT事件
调用WSAEventSelect函数时,有连接请求需要建立
连接请求到达,未有发送FD_ACCEPT事件
调用accept()函数后,还有连接请求需要建立
4. FD_CONNECT事件
调用WSAEventSelect函数时,一个连接已经建立完成
调用connect()函数后,建立连接完成时
5. FD_CLOSE事件
调用WSAEventSelect函数时,socket连接关闭
从容关闭,没有数据可读
执行shutdown()从容关闭,对方应答FIN后,无数据需要读取
对方关闭连接,WSAECONNRESET错误发生
WSAEventSelect()函数原型如下:
int WSAEventSelect(
SOCKET s, //一个标识套接口的描述字
WSAEVENT hEventObject, //是一个由WSACreateEvent(?)函数创建的事件对象句柄,用于标识与所提供的FD_XXX网络事件集合相关的一个事件对象
long lNetworkEvents //指定应用程序感兴趣的各种网络事件(FD_XXX)的组合
);
以下为测试WSAEventSelect()函数的程序,一个服务器端两个客户端
下面是服务器端程序:
/************************************************************************/ /* 事件对象I/O管理程序实例 */ /************************************************************************/ #include <WINSOCK2.H> #pragma comment(lib,"ws2_32") #include <stdio.h> int main() { printf("服务端程序\n"); //------①加载---------- WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2),&wsaData)!=0) { printf("WSAStartup Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("①加载成功\n"); //-------②创建流式套接字------------ SOCKET s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (s==INVALID_SOCKET) { printf("socket() Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("②已创建监听套接口:【%d】\n",s); //将套接口s置于”非阻塞模式“ u_long u1=1; ioctlsocket(s,FIONBIO,(u_long*)&u1); //-----------③绑定本地地址--------------------- struct sockaddr_in Sadd; Sadd.sin_family=AF_INET; Sadd.sin_port=htons(5555); Sadd.sin_addr.S_un.S_addr=inet_addr("192.168.31.1"); if (bind(s,(sockaddr*)&Sadd,sizeof(Sadd))==SOCKET_ERROR) { printf("bind() Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("③绑定成功,本地IP地址:【%s】,端口号:【%d】\n",inet_ntoa(Sadd.sin_addr),ntohs(Sadd.sin_port)); //--------------④进入监听状态----------------- if (listen(s,5)==SOCKET_ERROR) { printf("listen Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("④进入监听状态\n"); //--------------⑤创建事件对象----------------- WSAEVENT NewEvent=WSACreateEvent(); if (NewEvent==WSA_INVALID_EVENT) { printf("WSACreateEvent() Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("⑤创建一个事件对象,返回的事件对象句柄NewEvent=%d\n",NewEvent); //--------------⑥网络事件注册------------ int WESerror=WSAEventSelect(s,NewEvent,FD_ACCEPT|FD_CLOSE); if (WESerror==INVALID_SOCKET) { printf("WSAEventSelect() Failed,Error=【%d】\n",WSAGetLastError()); return -1; } else printf("⑥套接口【%d】、事件对象【%d】和网络事件FD_ACCEPT|FD_CLOSE已关联\n",s,NewEvent); //-----------准备工作--------------- int t=1; WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS]; SOCKET sockArray[WSA_MAXIMUM_WAIT_EVENTS]; int n=0; eventArray =NewEvent; sockArray =s; n++; //------------循环处理------------- while (true) { //---------------⑦等待事件对象-------------- int nIndex=WSAWaitForMultipleEvents(n,eventArray,FALSE,40000,FALSE); printf("nIndex=%d\n",nIndex); if (nIndex==WSA_WAIT_FAILED)//------7.1调用失败--------- { printf("调用失败\n"); break; } else if (nIndex==WSA_WAIT_TIMEOUT)//-------7.2超时--------- { if (t<3) { printf("第【%d】次超时\n",t); t++; continue; } else { printf("第【%d】次超时,退出\n",t); break; } } //---------------7.3网络事件触发事件对象句柄的工作状态-------- else { WSANETWORKEVENTS event;//该结构记录网络事件和对应出错代码 //---------⑧网络事件查询----------- WSAEnumNetworkEvents(sockArray[nIndex-WSA_WAIT_EVENT_0],NULL,&event); WSAResetEvent(eventArray[nIndex-WSA_WAIT_EVENT_0]); if ((event.lNetworkEvents&FD_ACCEPT)!=0) //------8.1处理FD_ACCEPT通知消息 { if (event.iErrorCode[FD_ACCEPT_BIT]==0) { if (n>WSA_MAXIMUM_WAIT_EVENTS) { printf("Too many connections!\n"); break; } SOCKET sNew=accept(sockArray[nIndex-WSA_WAIT_EVENT_0],NULL,NULL); NewEvent=WSACreateEvent(); WSAEventSelect(sNew,NewEvent,FD_READ|FD_CLOSE); eventArray =NewEvent; /* 将新的连接加入数组 */ sockArray =sNew; n++; } } else if (event.lNetworkEvents&FD_READ) //-------8.2处理FD_READ通知消息 { if (event.iErrorCode[FD_READ_BIT]==0) { char buf[256]; memset(buf,0,256); int nRecv=recv(sockArray[nIndex-WSA_WAIT_EVENT_0],buf,sizeof(buf),0); if (nRecv>0) { printf("接收到客户端【%d】数据:%s\n",sockArray[nIndex-WSA_WAIT_EVENT_0],buf); } } } else if (event.lNetworkEvents&FD_CLOSE) //---------8.3处理FD_CLOSE通知消息 { if (event.iErrorCode[FD_CLOSE_BIT]==0) { closesocket(sockArray[nIndex-WSA_WAIT_EVENT_0]); WSACloseEvent(eventArray[nIndex-WSA_WAIT_EVENT_0]); printf("套接字为【%d】的已关闭连接\n",sockArray[nIndex-WSA_WAIT_EVENT_0]); } else { if (event.iErrorCode[FD_CLOSE_BIT]==10053) { closesocket(sockArray[nIndex-WSA_WAIT_EVENT_0]); WSACloseEvent(eventArray[nIndex-WSA_WAIT_EVENT_0]); printf("客户端【%d】非法关闭连接\n",sockArray[nIndex-WSA_WAIT_EVENT_0]); } } for (int j=nIndex-WSA_WAIT_EVENT_0;j<n-1;j++) { sockArray[j]=sockArray[j+1]; eventArray[j]=eventArray[j+1]; } n--; } }// end 网络事件触发 }//end while printf("退出服务器程序\n"); closesocket(s); WSACleanup(); return 0; } view plaincopy to clipboardprint? //Client 1 #include <winsock2.h> #pragma comment(lib,"WS2_32") #include <stdio.h> int main() { printf("客户端程序/n"); //----------------①???加??载?--------------------------------------------------------- WSADATA wsaData; WORD wVersionRequested=MAKEWORD(2,2); if(WSAStartup(wVersionRequested,&wsaData)!=0){ printf("WSAStartup() Failed,Error=/n",WSAGetLastError()); return 1; } else printf("①加载成功|/n"); //----------------②???创???建??流???式??套???节??字??------------------------------------------------ SOCKET c1; c1 = socket(AF_INET, SOCK_STREAM,0); if(c1 == INVALID_SOCKET){ printf("socket() Failed,Error=/n",WSAGetLastError()); return 1; } else printf("②已创建连接套接字:【?%d 】/n",c1); //----------------绑???定??本??地??地??址??------------------------------------------------ struct sockaddr_in C1add; C1add.sin_family=AF_INET; C1add.sin_port=htons(2222); C1add.sin_addr.s_addr=inet_addr("192.168.31.2"); if(bind(c1,(sockaddr*)&C1add,sizeof(C1add))==SOCKET_ERROR){ printf("bind() Failed,Error=/n",WSAGetLastError()); return 1; } else printf("绑定成功,本地IP地址:【%s 】,端口号:【 %d 】/n",inet_ntoa(C1add.sin_addr),ntohs(C1add.sin_port)); //------------------③??连??接??请?求??------------------------------------------------ struct sockaddr_in Sadd; Sadd.sin_family=AF_INET; Sadd.sin_port=htons(5555); Sadd.sin_addr.s_addr=inet_addr("192.168.31.1"); if(connect(c1, (sockaddr*)&Sadd, sizeof(Sadd)) == -1){ printf(" Failed connect(),Error=【 %d 】/n",WSAGetLastError()); return 1; } else //*************************连??接??成??功|,可??以?? 开a始??发???送??、??接??收??************************* { printf("③连接成功|,服t务器IP地址:【 %s 】,端口号:【 %d 】/n",inet_ntoa(Sadd.sin_addr),ntohs(Sadd.sin_port)); int a; printf("希望发送数y据Y吗e?(键入“??1”??发???送??)"); scanf("%d",&a); while(a==1) //------循-环??处?|理???------ { //-----发???送??------ char S_buf[] = "Hello!I am a client 1"; int isend=send(c1,S_buf,strlen(S_buf),0); if(isend==SOCKET_ERROR){ printf("Failed send(),Error=【? %d 】?,或??者?服?t务?器??意?a外?a关?闭??/n",WSAGetLastError()); return 1; } else if(isend!=0) printf("信?息??【? %s 】?已??发???送??/n",S_buf); else printf("信?息??无T法???发???送??给?服?t务?端?/n"); printf("希??望??继??续?发???送??数?y据Y吗e???(键??入??“??1”??继??续?发???送??)"); scanf("%d",&a); if(a!=1) break; } //------end 循-环??处?|理???------ } //*************************end 开a始??发???送??、??接??收??************************* //------------------④???关?闭??、??释???放??------------------------------------------------ closesocket(c1); WSACleanup(); printf("④???与??服?t务?器??连??接??完???毕??/n"); return 0; }
相关文章推荐
- winsock IO模型 WSAEventSelect
- WinSock IO模型四: 重叠I/O (完成例程)
- Winsock Overlapped IO模型(二)
- winsock的io模型(终极篇)
- winsock IO模型 完成端口
- 在Winsock中实现异步的方法有很多,Winsock的IO模型有下面六种
- winsock IO模型 重叠端口
- Winsock IO模型之select模型
- Winsock IO模型之select模型
- WinSock IO模型---重叠模型
- WinSock IO模型五: 完成端口
- 总结网络IO模型与select模型的Python实例讲解
- winsock IO模型 完成端口
- Winsock IO模型之WSAEventSelect模型
- winsock IO模型 select模型
- WinSock IO模型二: WSAAsyncSelect 消息机制
- WinSock IO模型一: select 模型
- WinSock IO模型 -- WSAEventSelect模型事件触发条件说明
- IO复用模型同步,异步,阻塞,非阻塞及实例详解
- winsock IO模型 重叠端口