集美大学计算机工程学院实验报告课程名称:Windows网络与通信程序设计班级实验成绩:指导教师:余元辉姓名:实验项目名称:基于TCP的服务器客户端通信程序设计学号:上机实践日期:2015-04-24实验项目编号:07组号:五上机实践时间:2学时一、实验目的了解基于Select模型通信程序的编写,编译和执行二、实验内容与设计思想编写Win32程序模拟实现基于Select模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递。客户端向服务器端发送“计算从1到100的奇数和”,服务器回应客户端给出从1到100的奇数和结果。三、实验使用环境操作系统:MicrosoftWindowsXPSP2编程环境:VisualC++6.0四、实验步骤和调试过程本次实验中服务器选择的IP地址为:192.168.221.130,客户端的IP地址为192.168.221.130Server#includeInitSock.h#includestdio.h#includestring.h#includestdlib.hCInitSockinitSock;intmain(intargc,char*argv[]){//创建套接字SOCKETsListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(sListen==INVALID_SOCKET){printf(socketerror!);return0;}//绑定IP和端口sockaddr_insin;sin.sin_family=AF_INET;sin.sin_port=htons(5555);sin.sin_addr.S_un.S_addr=INADDR_ANY;if(bind(sListen,(LPSOCKADDR)&sin,sizeof(sin))==SOCKET_ERROR){printf(binderror!);}::listen(sListen,5);intitotal=0;intii;for(ii=1;ii=100;ii++){if(ii%2==1){itotal+=ii;}}fd_setfdSocket;FD_ZERO(&fdSocket);FD_SET(sListen,&fdSocket);while(true){fd_setfdRead=fdSocket;intnRet=::select(0,&fdRead,NULL,NULL,NULL);if(nRet0){for(inti=0;i(int)fdSocket.fd_count;i++){if(FD_ISSET(fdSocket.fd_array[i],&fdRead)){if(fdSocket.fd_array[i]==sListen){if(fdSocket.fd_countFD_SETSIZE){sockaddr_inaddrRemote;intnAddrLen=sizeof(addrRemote);SOCKETsNew=::accept(sListen,(SOCKADDR*)&addrRemote,&nAddrLen);FD_SET(sNew,&fdSocket);printf(接收到连接(%s)\n,::inet_ntoa(addrRemote.sin_addr));}else{printf(连接数量过多!\n);continue;}}else{//接收数据charszText[256];intnRecv=::recv(fdSocket.fd_array[i],szText,strlen(szText),0);if(nRecv0){szText[nRecv]='\0';printf(接收到数据:%s\n,szText);//发送数据charstr[10];charstr1[20]=1到100的奇数和为:;itoa(itotal,str,10);char*sendData=strcat(str1,str);::send(fdSocket.fd_array[i],sendData,strlen(sendData),0);}else{::closesocket(fdSocket.fd_array[i]);FD_CLR(fdSocket.fd_array[i],&fdSocket);}}}}}else{printf(选择失败!\n);break;}}return0;}Client#includeInitSock.h#includestdio.hCInitSockinitSock;intmain(intargc,char*argv[]){SOCKETsclient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(sclient==INVALID_SOCKET){printf(invalidsocket!);return0;}sockaddr_inserAddr;serAddr.sin_family=AF_INET;serAddr.sin_port=htons(5555);serAddr.sin_addr.S_un.S_addr=inet_addr(192.168.221.130);if(connect(sclient,(sockaddr*)&serAddr,sizeof(serAddr))==SOCKET_ERROR){printf(connecterror!);closesocket(sclient);return0;}charsdData[256];printf(发送给服务器:);scanf(%s,sdData);send(sclient,sdData,strlen(sdData),0);charrecData[255];intret=recv(sclient,recData,255,0);if(ret0){recData[ret]=0x00;printf(recData);printf(\n);}closesocket(sclient);WSACleanup();return0;}实验结果:五、实验小结(必写)首先遇到这样的问题,服务器进程终止,那么在终止时刻,socketfd会正常关闭,也就是说内核会往客户端发送FIN消息。此时如果客户端进程没有堵塞与read,而是仍然write数据给服务器,则服务器会返回RST消息;如果客户端连续多次write调用,第一个write引起服务器RST消息,客户端内核收到RST消息后,进程仍然write数据,内核会向进程发送SIGPIPE信号,该信号默认行为为终止进程,同时write会返回EPIPE错误。那么是否捕获该信号,则由于具体业务决定。还有就是实验运行时如果换到另一台机子上时必须改成它的IP,否则会抱错而对接受的数据进行操作,题目要求是当服务器受到客服端发送的“计算1到100的奇数和”时,服务器才回应客户端给出1到100的奇数和结果。如果服务器受到的不是“计算1到100的奇数和”,就发送一个提示信息,告诉客户端“输入指令有误,请输入!”避免客户端空等的状况。最后,经过这次TCP/IP实验,我们学会了TCP协议下通信程序的编写,编译和执行,同时也深刻体会到了团队协作的重要性六、附录《网络编程技术与应用》