集美大学计算机工程学院实验报告课程名称:TCP/IP协议与通信程序设计班级:网络实验成绩:实验项目名称:基于WSAEventSelect模型的通信程序设计学号:上机实践日期:2016-05-19实验项目编号:09组号:1上机实践时间:2学时一、实验目的了解基于WSAEventSelect模型通信程序的编写,编译和执行二、实验内容与设计思想编写Win32程序模拟实现基于WSAEventSelect模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递。客户端向服务器端发送“请输出从1到1000内所有的水仙花数”,服务器回应客户端给出结果。(水仙花数是一个三位数,它等于各位数字的立方和,例如153)三、实验使用环境操作系统:MicrosoftWindowsXPSP2编程环境:VisualC++6.0四、实验步骤和调试过程源代码:服务器:#includestdio.h#includewinsock2.h#pragmacomment(lib,WS2_32)//链接到WS2_32.lib#includemath.h#defineWM_SOCKETWM_USER+101//自定义消息classCInitSock{public:CInitSock(BYTEminorVer=2,BYTEmajorVer=2){//初始化WS2_32.dllWSADATAwsaData;WORDsockVersion=MAKEWORD(minorVer,majorVer);if(::WSAStartup(sockVersion,&wsaData)!=0)return;}~CInitSock(){::WSACleanup();}};//初始化Winsock库CInitSocktheSock;boolisnarcissus(intn){//判断n是否为水仙花数inti,j,k;//将3位数的个,十,百位分别提取出来i=n/100;j=(n%100)/10;k=(n%100)%10;if((i*100+j*10+k)==((i*i*i)+(j*j*j)+(k*k*k)))returntrue;returnfalse;};char*getallnarcissus(intn){//将n以内的所有水仙花数放在同一字符串中charsznarcissus[4096]=水仙化数:;intlen=strlen(sznarcissus)+strlen(,);if(n=1000)//因为水仙花数是一个三位数,若大于三位数将其置为999n=999;for(inti=100;i=n;i++){if(isnarcissus(i)){charsznum[5];itoa(i,sznum,10);//因为接收发送数据只处理字符串数组类型,使用itoa转换int型为字符数组类型char*sztemp=strcat(sznarcissus,sznum);//将每次判断的水仙花数添加到字符串数组中len+=strlen(sznum);sznarcissus[len-1]=',';len+=strlen(,);}}returnsznarcissus;};intmain(){//事件句柄和套节字句柄表WSAEVENTeventArray[WSA_MAXIMUM_WAIT_EVENTS];SOCKETsockArray[WSA_MAXIMUM_WAIT_EVENTS];intnEventTotal=0;USHORTnPort=4567;//此服务器监听的端口号//创建监听套节字SOCKETsListen=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);sockaddr_insin;sin.sin_family=AF_INET;sin.sin_port=htons(nPort);sin.sin_addr.S_un.S_addr=INADDR_ANY;if(::bind(sListen,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR){printf(Failedbind()\n);return-1;}::listen(sListen,5);//创建事件对象,并关联到新的套节字WSAEVENTevent=::WSACreateEvent();::WSAEventSelect(sListen,event,FD_ACCEPT|FD_CLOSE);//添加到表中eventArray[nEventTotal]=event;sockArray[nEventTotal]=sListen;nEventTotal++;//处理网络事件while(TRUE){//在所有事件对象上等待intnIndex=::WSAWaitForMultipleEvents(nEventTotal,eventArray,FALSE,WSA_INFINITE,FALSE);//对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态nIndex=nIndex-WSA_WAIT_EVENT_0;for(inti=nIndex;inEventTotal;i++){nIndex=::WSAWaitForMultipleEvents(1,&eventArray[i],TRUE,1000,FALSE);if(nIndex==WSA_WAIT_FAILED||nIndex==WSA_WAIT_TIMEOUT){continue;}else{//获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件WSANETWORKEVENTSevent;::WSAEnumNetworkEvents(sockArray[i],eventArray[i],&event);if(event.lNetworkEvents&FD_ACCEPT)//处理FD_ACCEPT通知消息{if(event.iErrorCode[FD_ACCEPT_BIT]==0){if(nEventTotalWSA_MAXIMUM_WAIT_EVENTS){printf(Toomanyconnections!\n);continue;}SOCKETsNew=::accept(sockArray[i],NULL,NULL);WSAEVENTevent=::WSACreateEvent();::WSAEventSelect(sNew,event,FD_READ|FD_CLOSE|FD_WRITE);//添加到表中eventArray[nEventTotal]=event;sockArray[nEventTotal]=sNew;nEventTotal++;}}elseif(event.lNetworkEvents&FD_READ)//处理FD_READ通知消息{if(event.iErrorCode[FD_READ_BIT]==0){charszText[256];intnRecv=::recv(sockArray[i],szText,strlen(szText),0);//接收客户端发送的数据if(nRecv0){szText[nRecv]='\0';printf(接收到数据:%s\n,szText);char*szReply=getallnarcissus(1000);//得到1到1000内所有的水仙花数::send(sockArray[i],szReply,strlen(szReply),0);//发送数据到客户端}}}elseif(event.lNetworkEvents&FD_CLOSE)//处理FD_CLOSE通知消息{if(event.iErrorCode[FD_CLOSE_BIT]==0){::closesocket(sockArray[i]);for(intj=i;jnEventTotal-1;j++){sockArray[j]=sockArray[j+1];sockArray[j]=sockArray[j+1];}nEventTotal--;}}elseif(event.lNetworkEvents&FD_WRITE)//处理FD_WRITE通知消息{}}}}return0;}客户端:#includestdio.h#includewinsock2.h#pragmacomment(lib,WS2_32)//链接到WS2_32.libclassCInitSock{public:CInitSock(BYTEminorVer=2,BYTEmajorVer=2){//初始化WS2_32.dllWSADATAwsaData;WORDsockVersion=MAKEWORD(minorVer,majorVer);if(::WSAStartup(sockVersion,&wsaData)!=0)return;}~CInitSock(){::WSACleanup();}};CInitSocktheSock;//加载套接字库intmain(){//创建套节字SOCKETs=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(s==INVALID_SOCKET){printf(Failedsocket()\n);return0;}//也可以在这里调用bind函数绑定一个本地地址,无则系统将会自动安排//填写远程地址信息sockaddr_inservAddr;servAddr.sin_family=AF_INET;servAddr.sin_port=htons(4567);//要连接的服务器地址servAddr.sin_addr.S_un.S_addr=inet_addr(219.228.247.127);if(::connect(s,(sockaddr*)&servAddr,sizeof(servAddr))==-1){printf(Failedconnect()\n);return0;}//发送数据charbuf[]=请输出从1到1000内所有的水仙花数;printf(发送数据:%s\n,buf);send(s,buf,strlen(buf),0);Sleep(6);//接收数据charbuff[3000];intnRecv=::recv(s,buff,3000,0);if(nRecv0){buff[nRecv]='\0';printf(接收到数据:\n%s\n,buff);}//关闭套节字::closesocket(s);return0;}执行结果:五、实验小结1.执行结果出现将1-1000所有的数均发送即判断为水仙花数经查看判断水仙花数的函数isnarcissus(intn),发现在判断该数等于各位数字的立方和的if语句中,仅仅将为真的情况执行返回ture,漏掉将其它情况返回false。2.水仙花数特指3位数,所以当所要求的范围不在100-999之间时应将判断的范围调整为100-999,即进行for循环判断时以100开始,且用if(n=1000)n=999;语句进行相应的范围判断从而调整上界n的值六、附录《网络编程技术与应用》