实验三、WINSOCK套接字编程实验报告序号:姓名:学号:成绩:指导老师:1.实验目的:用C或JAVA语言编写客户端、服务器程序,实现基于TCP或UDP的网络通信数据传输服务,熟悉基于TCP或UDP的Socket编程原理。2.实验环境:建立在TCP/IP网络体系结构之上计算机网络实验环境。各计算机除了安装TCP/IP软件外,还安装了TCP/IP开发系统。计算机具备Windows环境中套接字socket的编程接口功能,可为用户提供全网范围的进程通信功能。3.实验指导:参见套接字编程实验指导4.实验步骤(1)运行指导书中给出的参考程序,分析实验结果,并回答问题(1)-(3)(2)根据给定参考程序修改代码,完善修改服务器和客户端的功能。并回答问题(4)-(5)5.实验结果分析(1)为什么在服务器和客户端要包含winsock2.h文件?答:windowssocket的头文件,不包含该头文件,关于socket编程的结构和函数等都不能被调用。(2)为什么在服务器和客户端程序中要加入#pragmacomment(lib,ws2_32.lib)语句,如果不加会出现什么问题?答:#pragmacomment(lib,Ws2_32.lib)表示链接Ws2_32.lib这个库。和在工程设置里写上链入Ws2_32.lib的效果一样,不过这种方法写的程序别人在使用你的代码的时候就不用再设置工程settings了。如果没有这个(3)为什么在服务器和客户端程序中要使用WSAStartup函数,如果不用,程序会有什么问题?答:使用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。该函数执行成功后返回0。如果不用,应用程序将无法调用socket函数。(4)修改后的程序完成实现了什么功能,附上修改后的源代码。(修改或填加的代码用波浪线标注,并填加注释),并附上实验截图实现功能:在有双方IP的情况下可以实现窗体界面的交互式聊天功能,可以中英文符号数字随意输入。截图:客户端:服务器:客户端代码:#includestdafx.h#includestdio.h#includestdlib.h#includeerrno.h#includestring.h#includesys/types.h#includewinsock2.h#includeconio.h#includewindows.h#pragmacomment(lib,ws2_32.lib)#definePORT3490/*客户机连接远程主机的端口*/#defineMAXDATASIZE100/*每次可以接收的最大字节*/int_tmain(intargc,_TCHAR*argv[]){WORDwVersionRequested;WSADATAwsaData;interr=0,rval=0;SOCKETfd;structsockaddr_inservaddr;structhostent*hp;charbuf[1024]=;wVersionRequested=MAKEWORD(2,2);err=WSAStartup(wVersionRequested,&wsaData);if(err!=0)return-1;if((fd=socket(AF_INET,SOCK_STREAM,0))0){printf(Cannotcreatesocket!);exit(2);}servaddr.sin_family=AF_INET;servaddr.sin_port=htons(PORT);hp=gethostbyname(113.55.38.221);//输入服务器ip地址//根据服务器的网络计算//机名称得到其IP地址等信息memcpy((char*)&servaddr.sin_addr,(char*)hp-h_addr,hp-h_length);memset(servaddr.sin_zero,0,sizeof(servaddr.sin_zero));//和服务器创建连接rval=connect(fd,(sockaddr*)&servaddr,sizeof(servaddr));if(rval0){//创建连接失败printf(Cannotcreateconnect!);exit(3);}elsewhile(1){{memset(buf,0,1024);printf(客户端--〉:);scanf(%s,&buf);//向服务器发送信息rval=send(fd,buf,strlen(buf)+1,0);if(rval0)printf(Writeerror!);if((rval=recv(fd,buf,sizeof(buf),0)0))perror(readingstreammessage);if(rval==0)printf(服务器--〉:%s\n,buf);}}closesocket(fd);exit(5);}服务器代码:#includestdafx.h#includestdio.h#includestdlib.h#includeerrno.h#includestring.h#includesys/types.h#includeconio.h#includewinsock2.h#includewindows.h#pragmacomment(lib,ws2_32.lib)#defineMYPORT3490/*定义用户连接端口*/#defineBACKLOG10/*多少等待连接控制*/#defineSERVER_IP_ADDR113.55.38.221//输入本机ip地址/*服务器的IP地址*/int_tmain(intargc,_TCHAR*argv[]){SOCKETsock,msgsock;intlength=0;structsockaddr_inserver;structsockaddrtcpaddr;charbuf[1024]=;intrval=0,len=0,err=0;WORDwVersionRequested;WSADATAwsaData;/*指定socket版本,否则创建socket失败,即使创建socket返回值不为-1,但是bind时会失败*/wVersionRequested=MAKEWORD(2,2);err=WSAStartup(wVersionRequested,&wsaData);if(err!=0)return-1;/*建立套接字*/sock=socket(AF_INET,SOCK_STREAM,0);if(sock0){perror(openingstreamsocket);exit(1);}/*使用任意端口命名套接字*/server.sin_family=AF_INET;server.sin_port=htons(MYPORT);server.sin_addr.s_addr=inet_addr(SERVER_IP_ADDR);memset(server.sin_zero,0,sizeof(server.sin_zero));//将服务器地址与socket绑定在一起rval=bind(sock,(structsockaddr*)&server,sizeof(server));if(rval0){perror(bindingstreamsocket);exit(1);}//找出指定的端口号并打印出来length=sizeof(server);if(getsockname(sock,(structsockaddr*)&server,&length)0){perror(gettingsocketname);exit(1);}printf(socketport#%d\n,ntohs(server.sin_port));//开始接收连接,最大请求数为listen(sock,5);len=sizeof(structsockaddr);do{msgsock=accept(sock,(structsockaddr*)&tcpaddr,(int*)&len);if(msgsock==-1)perror(accept);else{while(1){memset(buf,0,sizeof(buf));if((rval=recv(msgsock,buf,sizeof(buf),0)0))perror(readingstreammessage);if(rval==0)printf(客户端--〉%s\n,buf);printf(服务器--);scanf(%s,&buf);rval=send(msgsock,buf,strlen(buf)+1,0);}}closesocket(msgsock);}while(TRUE);/*因为这个程序已经有了一个无限循环,所以套接字sock从来不显式关闭。然而,当进程被杀死或正常终止时,所有套接字都将自动地被关闭。*/closesocket(msgsock);return0;}(5)请详细说明此实验在设计及运行时遇到的问题和解决办法,及实验体会及建议。答:1.通过修改给定的代码,让客户端喝服务器无限循环,让TCP链接不断开,并让CS双方都可以发生并打印消息。但是运行的时候还是会存在一些问题,经过查阅资料,能够基本解决这些问题。2.通过这次试验对套接字编程有了更深入的了解。