计算机网络实验报告实验三Socket通信实验姓名:班级:计科1101班学号:0909110122实验时间:11月27日2目录一、实验目的与要求------------------------------------------------------3二、编程语言和环境------------------------------------------------------3三、问题分析---------------------------------------------------------------4四、具体实现及源代码---------------------------------------------------5五、调试与运行结果------------------------------------------------------8六、实验心得--------------------------------------------------------------93一、实验目的与要求网络编程是通过使用套接字来达到进程间通信目的的编程,Socket编程是网络编程的主流工具,SocketAPI是实现进程间通信的一种编程设施,也是一种为进程间提供底层抽象的机制,提供了访问下层通信协议的大量系统调用和相应的数据结构。本实验利用SocketAPI编写网络通信程序,具体实验要求及内容如下:1.掌握VB、VC++、VS或JAVA等集成开发环境编写网络程序的方法;2.掌握客户/服务器(C/S)应用的工作方式;3.学习网络中进程之间通信的原理和实现方法;4.理解单播、组播和广播的原理并比较其不同之处;5.要求本机既是客户端又是服务器端;所编写的程序应具有如下功能:1.具有点对点通信功能,任意客户端之间能够发送消息;2.具有群组通信功能,客户端能够向组内成员同时发送消息,其他组成员不能收到;3.具有广播功能,客户端能够向所有其他成员广播消息;二、编译语言与环境1.编程语言C/C++/C#/Java等均可;本次实验采用C语言版本2.编程环境Windows(MSVisual系列,VC/VB/VS.Net;)和Linux(编辑器vi+编译器GCC)均可;在Windows下可使用。4三、问题分析1、建立连接1)服务程序调用socket创建一个新的套接字,并在传输层实体中分配表空间,返回一个文件描述符用于以后调用中使用该套接字;调用bind将一个地址赋予该套接字,使得远程客户程序能访问该服务程序;调用listen分配数据空间,以便存储多个用户的连接建立请求;调用accept将服务程序阻塞起来,等待接收客户程序发来的连接请求。当传输层实体接收到建立连接的TPDU时,新创建一个和原来的套接字相同属性的套接字并返回其文件描述符。服务程序创建一个子进程处理此次连接,然后继续等待发往原来套接字的连接请求。2)客户程序调用socket创建一个新的套接字,并在传输层实体中分配表空间,返回一个文件描述符用于在以后的调用中使用该套接字;调用connect阻塞客户程序,传输层实体开始建立连接,当连接建立完成时,取消阻塞;2、数据传输双方使用send和receive完成数据的全双工发送。3、释放连接每一方使用close原语单独释放连接。四、具体实现及源代码服务器端#includeWinsock2.h#includestdio.h5#pragmacomment(lib,ws2_32.lib)voidmain(){interr;//错误信息intlen;charsendBuf[100];//发送至客户端的字符串charrecvBuf[100];//接受客户端返回的字符串SOCKETsockServer;//服务端SocketSOCKADDR_INaddrServer;//服务端地址SOCKETsockClient;//客户端ScoketSOCKADDR_INaddrClient;//客户端地址WSADATAwsaData;//winsock结构体WORDwVersionRequested;//winsock的版本//配置WindowsSocket版本wVersionRequested=MAKEWORD(2,2);//初始化WindowsSocketerr=WSAStartup(wVersionRequested,&wsaData);if(err!=0){//启动错误,程序结束return;}/**确认WinSockDLL支持2.2*请注意如果DLL支持的版本大于2.2至2.2*它仍然会返回wVersion2.2的版本*/if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2){//启动错误,程序结束WSACleanup();//终止Winsock2DLL(Ws2_32.dll)的使用return;}6//定义服务器端socketsockServer=socket(AF_INET,SOCK_STREAM,0);//设置服务端socketaddrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//本机IPaddrServer.sin_family=AF_INET;//协议类型是INETaddrServer.sin_port=htons(6000);//绑定端口6000//将服务器端socket绑定在本地端口bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));//Listen监听端口listen(sockServer,5);//5为等待连接数目printf(服务器已启动:\n监听中...\n);len=sizeof(SOCKADDR);while(1){//accept会阻塞进程,直到有客户端连接上来为止sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len);//当客户端连接上来时,拼接如下字符串sprintf(sendBuf,欢迎ip:%s的用户连接,这里是Lellansin的服务器\n,inet_ntoa(addrClient.sin_addr));//向客户端发送字符串send(sockClient,sendBuf,strlen(sendBuf)+1,0);//获取客户端返回的数据recv(sockClient,recvBuf,100,0);//打印客户端返回的数据printf(%s\n,recvBuf);//关闭socketclosesocket(sockClient);}}客户端#includeWinsock2.h#includestdio.h7#pragmacomment(lib,ws2_32.lib)voidmain(){interr;char*message;charrecvBuf[100];SOCKETsockClient;//客户端ScoketSOCKADDR_INaddrServer;//服务端地址WSADATAwsaData;WORDwVersionRequested;wVersionRequested=MAKEWORD(2,2);err=WSAStartup(wVersionRequested,&wsaData);if(err!=0){return;}if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2){//启动错误,程序结束WSACleanup();return;}//新建客户端scoketsockClient=socket(AF_INET,SOCK_STREAM,0);//定义要连接的服务端地址addrServer.sin_addr.S_un.S_addr=inet_addr(175.0.170.28);//目标IP(175.0.170.28是本机地址)addrServer.sin_family=AF_INET;//协议类型是INETaddrServer.sin_port=htons(6000);//连接端口12348//让sockClient连接到服务端connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));//从服务端获取数据recv(sockClient,recvBuf,100,0);//打印数据printf(%s\n,recvBuf);message=服务端你好~;//发送数据到服务端send(sockClient,message,strlen(message)+1,0);//关闭socketclosesocket(sockClient);WSACleanup();getchar();//暂停}五、运行结果六、实验心得通过本次实验能够感受到网络在实际当中的运用,使我对网络编程有了更深的概念。同时让我发现自己知识结构的欠缺。虽然基本功9能已经实现,但还是存在很多不稳定的问题尚待解决。此次实验是对Socket的一个应用,让我更深的了解了Socket函数的作用及使用方法。实验过程中遇到了很多的问题,例如:程序只能通信一次。刚开始我以为建立的socket套接口只要建立一次并更新连接地址就可以多次使用。当初不知道问题存在的在于这,在程序加入很多错误报告代码,发现再客户端再次connect的时候返回负值。在网上查看很多相关代码之后,发现问题所在,把建立socket的代码写进客户端的循环体中,每次通信都重新建立socket套接口就可以了。