集美大学计算机工程学院实验报告课程名称:TCP/IP协议分析与编程班级:实验成绩:实验项目名称:基于重叠模型的通信程序设计学号:上机实践日期:2016-05-26实验项目编号:10组号:1上机实践时间:2学时一、实验目的了解基于重叠模型通信程序的编写,编译和执行二、实验内容与设计思想编写Win32程序实现基于重叠模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递。客户端向服务器端发送“请输出1000以内斐波那契数列”,服务器回应客户端给出结果。(斐波那契数列特征,F0=0,F1=1,Fn=F(n-1)+F(n-2),n=2)三、实验使用环境操作系统:MicrosoftWindowsXPSP2编程环境:VisualC++6.0四、实验步骤和调试过程源代码服务器端:#includestdafx.h#includeinitsock.h#includeMswsock.h#includestdio.h#defineBUFFER_SIZE1024CInitSockinitSock;//为每个套节字创建一个_SOCKET_OBJ对象typedefstruct_SOCKET_OBJ{SOCKETs;//套节字句柄intnOutstandingOps;//记录此套节字上的重叠I/O数量LPFN_ACCEPTEXlpfnAcceptEx;//扩展函数AcceptEx的指针(仅对监听套节字而言)}SOCKET_OBJ,*PSOCKET_OBJ;//定义缓冲区对象buffer,记录重叠I/O的所有属性typedefstruct_BUFFER_OBJ{OVERLAPPEDol;//重叠结构char*buff;//send/recv/AcceptEx所使用的缓冲区intnLen;//buff的长度PSOCKET_OBJpSocket;//此I/O所属的套节字对象intnOperation;//提交的操作类型#defineOP_ACCEPT1#defineOP_READ2#defineOP_WRITE3SOCKETsAccept;//用来保存AcceptEx接受的客户套节字(仅对监听套节字而言)_BUFFER_OBJ*pNext;}BUFFER_OBJ,*PBUFFER_OBJ;HANDLEg_events[WSA_MAXIMUM_WAIT_EVENTS];//I/O事件句柄数组intg_nBufferCount;//上数组中有效句柄数量PBUFFER_OBJg_pBufferHead,g_pBufferTail;//记录缓冲区对象组成的表的地址//申请套节字对象和释放套节字对象的函数PSOCKET_OBJGetSocketObj(SOCKETs){PSOCKET_OBJpSocket=(PSOCKET_OBJ)::GlobalAlloc(GPTR,sizeof(SOCKET_OBJ));if(pSocket!=NULL){pSocket-s=s;}returnpSocket;}voidFreeSocketObj(PSOCKET_OBJpSocket){if(pSocket-s!=INVALID_SOCKET)::closesocket(pSocket-s);::GlobalFree(pSocket);}//申请_BUFFER_OBJ对象的函数,每次调用重叠I/0函数前需要申请PBUFFER_OBJGetBufferObj(PSOCKET_OBJpSocket,ULONGnLen){if(g_nBufferCountWSA_MAXIMUM_WAIT_EVENTS-1)returnNULL;PBUFFER_OBJpBuffer=(PBUFFER_OBJ)::GlobalAlloc(GPTR,sizeof(BUFFER_OBJ));if(pBuffer!=NULL){pBuffer-buff=(char*)::GlobalAlloc(GPTR,nLen);pBuffer-ol.hEvent=::WSACreateEvent();pBuffer-pSocket=pSocket;pBuffer-sAccept=INVALID_SOCKET;//将新的BUFFER_OBJ添加到列表中if(g_pBufferHead==NULL){g_pBufferHead=g_pBufferTail=pBuffer;}else{g_pBufferTail-pNext=pBuffer;g_pBufferTail=pBuffer;}g_events[++g_nBufferCount]=pBuffer-ol.hEvent;}returnpBuffer;}//释放_BUFFER_OBJ对象的函数voidFreeBufferObj(PBUFFER_OBJpBuffer){//从列表中移除BUFFER_OBJ对象PBUFFER_OBJpTest=g_pBufferHead;BOOLbFind=FALSE;if(pTest==pBuffer){g_pBufferHead=g_pBufferTail=NULL;bFind=TRUE;}else{while(pTest!=NULL&&pTest-pNext!=pBuffer)pTest=pTest-pNext;if(pTest!=NULL){pTest-pNext=pBuffer-pNext;if(pTest-pNext==NULL)g_pBufferTail=pTest;bFind=TRUE;}}//释放它占用的内存空间if(bFind){g_nBufferCount--;::CloseHandle(pBuffer-ol.hEvent);::GlobalFree(pBuffer-buff);::GlobalFree(pBuffer);}}//在缓冲区列表中查找_BUFFER_OBJ对象PBUFFER_OBJFindBufferObj(HANDLEhEvent){PBUFFER_OBJpBuffer=g_pBufferHead;while(pBuffer!=NULL){if(pBuffer-ol.hEvent==hEvent)break;pBuffer=pBuffer-pNext;}returnpBuffer;}//更新事件句柄数组g_eventsvoidRebuildArray(){PBUFFER_OBJpBuffer=g_pBufferHead;inti=1;while(pBuffer!=NULL){g_events[i++]=pBuffer-ol.hEvent;pBuffer=pBuffer-pNext;}}//提交接收连接的_BUFFER_OBJ对象BOOLPostAccept(PBUFFER_OBJpBuffer){PSOCKET_OBJpSocket=pBuffer-pSocket;if(pSocket-lpfnAcceptEx!=NULL){//设置I/O类型,增加套节字上的重叠I/O计数pBuffer-nOperation=OP_ACCEPT;pSocket-nOutstandingOps++;//投递此重叠I/ODWORDdwBytes;pBuffer-sAccept=::WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);BOOLb=pSocket-lpfnAcceptEx(pSocket-s,pBuffer-sAccept,pBuffer-buff,BUFFER_SIZE-((sizeof(sockaddr_in)+16)*2),sizeof(sockaddr_in)+16,sizeof(sockaddr_in)+16,&dwBytes,&pBuffer-ol);if(!b){if(::WSAGetLastError()!=WSA_IO_PENDING)returnFALSE;}returnTRUE;}returnFALSE;};//提交接收数据的_BUFFER_OBJ对象BOOLPostRecv(PBUFFER_OBJpBuffer){//设置I/O类型,增加套节字上的重叠I/O计数pBuffer-nOperation=OP_READ;pBuffer-pSocket-nOutstandingOps++;//投递此重叠I/ODWORDdwBytes;DWORDdwFlags=0;WSABUFbuf;buf.buf=pBuffer-buff;buf.len=pBuffer-nLen;if(::WSARecv(pBuffer-pSocket-s,&buf,1,&dwBytes,&dwFlags,&pBuffer-ol,NULL)!=NO_ERROR){if(::WSAGetLastError()!=WSA_IO_PENDING)returnFALSE;}returnTRUE;}//提交发送数据的_BUFFER_OBJ对象BOOLPostSend(PBUFFER_OBJpBuffer){//设置I/O类型,增加套节字上的重叠I/O计数pBuffer-nOperation=OP_WRITE;pBuffer-pSocket-nOutstandingOps++;//投递此重叠I/ODWORDdwBytes;DWORDdwFlags=0;WSABUFbuf;buf.buf=pBuffer-buff;buf.len=pBuffer-nLen;//计算1000以内斐波那契数列charstr[100]=1000以内斐波那契数列为:;charstr1[10];intx=0,y=1,z;for(inti=2;z=1000;i++){z=x+y;itoa(y,str1,10);strcat(str1,);strcat(str,str1);x=y;y=z;}buf.buf=str;buf.len=strlen(str);//发送数据给客户端printf(发送数据:\n);printf(%s,str);if(::WSASend(pBuffer-pSocket-s,&buf,1,&dwBytes,dwFlags,&pBuffer-ol,NULL)!=NO_ERROR){if(::WSAGetLastError()!=WSA_IO_PENDING)returnFALSE;}returnTRUE;}BOOLHandleIO(PBUFFER_OBJpBuffer){PSOCKET_OBJpSocket=pBuffer-pSocket;//从BUFFER_OBJ对象中提取SOCKET_OBJ对象指针,为的是方便引用pSocket-nOutstandingOps--;//获取重叠操作结果DWORDdwTrans;DWORDdwFlags;BOOLbRet=::WSAGetOverlappedResult(pSocket-s,&pBuffer-ol,&dwTrans,FALSE,&dwFlags);if(!bRet){//在此套节字上有错误发生,因此,关闭套节字,移除此缓冲区对象。//如果没有其它抛出的I/O请求了,释放此缓冲区对象,否则,等待此套节字上的其它I/O也完成if(pSocket-s!=INVALID_SOCKET){::closesocket(pSocket-s);pSocket-s=INVALID_SOCKET;}if(pSocket-nOutstandingOps==0)FreeSocketObj(pSocket);FreeBufferObj(pBuffer);returnFALSE;}//没有错误发生,处理已完成的I/Oswitch(pBuffer-nOperation){caseOP_ACCEPT://接收到一个新的连接,并接收到了对方发来的第一个封包{//为新客户创建一个SOCKET_OBJ对象PSOCKET_OBJpC