实验报告
课 程 计算机网络(双语)(课程设计) 实验名称 UDP及TCP通信程序的设计与实现 专业班级 姓 名 学 号
2013 年 5 月 30 日
计算机网络实验报告
目录
实验目的和内容............................................................................................................ 1
实验目的................................................................................................................. 1 实验内容................................................................................................................. 1 实验环境........................................................................................................................ 2 程序的逻辑框图............................................................................................................ 2
UDP通信程序的逻辑框图:................................................................................ 2 TCP通信程序的逻辑框图: ................................................................................... 3 程序源代码(数据结构的描述、核心算法) .............................................................. 4
1。TCP通信程序源代码 ............................................................................... 4 2.TCP通信程序数据结构的描述 .................................................................. 7 3。TCP通信程序的核心算法 ....................................................................... 7 4.UDP通信程序源代码.................................................................................. 8 5.UDP通信程序数据结构的描述................................................................ 11 6。UDP通信程序的核心算法..................................................................... 12
实验数据、结果分析.................................................................................................. 13
TCP通信程序实验结果分析 ....................................................................... 13 UDP通信程序实验结果分析....................................................................... 14
总结.............................................................................................................................. 16
实验目的和内容
实验目的
掌握win32平台下,使用winsock API来实现UDP通信程序和TCP通信程序。
实验内容
1. 实现控制台模式下,在单机上基于UDP的聊天程序;
2. 实现控制台模式下,在单机上基于TCP的聊天程序;
3. 上述两个程序,最简单的实现方式是:一方发送、另一方接收、交替进行;
4. 提交上述2个程序的源程序,程序代码有充分的注释,并填写实验报告,实验报告的主要
1
计算机网络实验报告
内容为说明程序设计的思路,程序代码的流程。
实验环境
在win7系统下,visual studio 2008环境下的win32平台下
程序的逻辑框图
UDP通信程序的逻辑框图:
Server端:s=socket()bind(s,(struct sockaddr far *)&lAddr, sizeof(lAddr))Recv(s,Msg, 80,0)Client端:s=socket()bind(s,(struct sockaddr far *)&lAddr, sizeof(lAddr))阻塞,等待客户请求sendto(S,Msg,strlen(Msg), 0,(struct sockaddr far *)&rAddr, l)处理服务请求Recv(s,Msg, 80,0)阻塞,等待服务数据sendto(S,Msg,strlen(Msg), 0,(struct sockaddr far *)&rAddr, l)Y继续NClosesocket(s)处理数据Y继续NClosesocket(s)
2
计算机网络实验报告
TCP通信程序的逻辑框图:
Server端:S=socket()Client端:Bind(s,(struct sockaddr far *)&lAddr, sizeof(lAddr))S=socket()Listen()Connect()阻塞,等待客户连接连接请求Accept()Send()Recv()Recv()阻塞,等待客户连接服务请求处理服务请求服务应答Send()处理数据Y继续NClosesocket(s)Closesocket(s)N阻塞,等待服务数据Y继续
3
计算机网络实验报告
程序源代码(数据结构的描述、核心算法)
1。TCP通信程序源代码 Client端:
#include \"stdafx.h\" #include 〈stdlib。h〉 #include int InitSock(BYTE minorVer = 2, BYTE majorVer = 2) { WSADATA wsaData; WORD sockVersion = MAKEWORD(minorVer, majorVer); if(WSAStartup(sockVersion, &wsaData) != 0) exit(0); return 1; } int main() { char rbuf[256]; char szText[256]; InitSock(); //创建socket,第一个参数表示用IP协议,第二个参数表示用TCP传输,第三个不大清楚 SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //判断socket是否创建成功 if(sListen == INVALID_SOCKET) { printf(\"Failed socket() \\n\"); return 0; } //用于存储IP地址和端口号的变量 sockaddr_in sin; sin.sin_family = AF_INET; //IP协议 4 计算机网络实验报告 sin。sin_port = htons(4567); //端口号 sin.sin_addr.S_un。S_addr = INADDR_ANY; //接收任何IP的连接 //绑定函数,将socket 与 IP地址和端口 绑定在一块 if(bind(sListen, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { printf(”Failed bind() \\n”); return 0; } //开始监听,第二个参数表示最大连接数 if(listen(sListen, 2) == SOCKET_ERROR) { printf(\"Failed listen() \\n”); return 0; } //定义一个新的变量 sockaddr_in remoteAddr; int nAddrLen = sizeof(remoteAddr); //用于存储连接客户端的socket SOCKET sClient; //accept函数会阻塞,直到等到有socket连接服务器为止,才继续往后执行,并将客户端的IP和端口号存在remoteAddr中 sClient = accept(sListen, (SOCKADDR*)&remoteAddr, &nAddrLen); printf(\"接收到一个连接%s \\r\\n\", inet_ntoa(remoteAddr。sin_addr)); while(TRUE) { if(sClient == INVALID_SOCKET) { printf(\"Failed accept()\"); continue; } printf(\"send:”); scanf(”%s\",szText); //发送函数,往sClient这个socket中发送szText send(sClient, szText, strlen(szText), 0); //recv为阻塞函数,等待sClient中传来数据 5 计算机网络实验报告 } int nRecv = recv(sClient, rbuf, 256, 0); if(nRecv〉0) { rbuf[nRecv] = '\\0’; printf(”receive:%s\\n”, rbuf); } } closesocket(sClient); closesocket(sListen); WSACleanup(); return 0; Server端: #include \"stdafx。h\" #include 〈stdlib。h> #include 〈stdio.h〉 #include 〈string.h> #include 〈winsock。h> //初始化函数,初始化版本号 int InitSock(BYTE minorVer = 2, BYTE majorVer = 2) { WSADATA wsaData; WORD sockVersion = MAKEWORD(minorVer, majorVer); if(WSAStartup(sockVersion, &wsaData) != 0) exit(0); return 1; } int main() { InitSock(); //创建socket,第一个参数表示用IP协议,第二个参数表示用TCP传输,第三个不大清楚 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == INVALID_SOCKET) { printf(\" Failed socket() \\n”); return 0; } //用于存储IP地址和端口号的变量 sockaddr_in servAddr; 6 计算机网络实验报告 servAddr。sin_family = AF_INET; servAddr。sin_port = htons(4567); //要连接的端口号 servAddr。sin_addr。S_un。S_addr = inet_addr(\"127。0。0.1\");//要连接的IP地址 //连接函数,是一个阻塞类型的函数,用s这个socket与服务器地址的某个端口连接,之后往s这个socket中写数据,服务器就能收到 if(connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1) { printf(\" Failed connect() \\n\"); return 0; } char buff[256]; char szText[256]; while(true){ //接收函数,是一个阻塞类型的函数,等待s这个socket中传来数据,256表示接收的最大字符数 int nRecv = recv(s, buff, 256, 0); if(nRecv 〉 0) { buff[nRecv] = ’\\0’; printf(”receive:%s\\n\", buff); } printf(\"send:”); scanf(\"%s”,szText); //发送函数,往s这个socket中发送szText这个字符串 send(s, szText, strlen(szText), 0); } closesocket(s); WSACleanup(); return 0; } 2.TCP通信程序数据结构的描述 (1)客户端及服务器都含有存储IP地址及端口号的数据结构,sockaddr_in remoteAddr; 和servAddr (2)用于存储连接客户端的socket: SOCKET sClient;和用于存储连接服务器的socket:SOCKET s 3。TCP通信程序的核心算法 服务器首先启动,通过调用socket( )建立一个套接口,然后bind( )将该套接口和本地地址(IP地址和端口)联系在一起,再listen( )使套接口做好侦听的准备,并规定它的请求队 7 计算机网络实验报告 列的长度, 之后就调用accept( )来接收连接,并获得客户机的地址信息;客户在建立套接口后就可调用connect( ) 和服务器建立连接; 连接一旦建立,客户机和服务器之间就可以通过调用:send( )和recv( ) (或read( )和write( ))来发送和接收数据; 最后,待数据传送结束后,双方调用closesocket() 关闭套接口。 4.UDP通信程序源代码 Client端: #include \"stdafx.h\" #include WORD RPort = 6666; //远程端口RemotePort char RIP[16]=\"127。0。0.1\"; //远程IP地址RemoteIPAddr WORD LPort = 7777; //本地端口LocalPort char LIP[16]=”127。0.0.1”; //本地IP地址LocalIPAddr SOCKET S; //套接口SOCKET struct sockaddr_in rAddr; //远程参数,remoteAddr struct sockaddr_in lAddr; //本地参数,localAddr WSADATA WD; //Winsock DLL信息 int r; //result; //--——--—---—----—-—————-----—-——-————-——-——————— void ShowInfo(char *info){ puts(info); exit(1); } //———-——--—-----———-—------——-———---—--——-———--—— void SetsockAddr(struct sockaddr_in *A,WORD Port,char *IP){ A—〉sin_family = AF_INET; //TCP/IP协议 A->sin_port = htons(Port); //端口 A—〉sin_addr.s_addr =inet_addr(IP); //IP 地址 } //-—----—-—--——-—-----—--—---—--—-—--——-—-———-—--- void main( ){ WORD v; //wVersionRequested; //—— — — — - - - - Startup Win socket — - - — — - — - v=0x0101; //0x0101 for v1。1, 0x0002 forv 2。0 r = WSAStartup(v, (LPWSADATA)&WD); 8 计算机网络实验报告 if(r != 0) ShowInfo(”Start_Error”); //—- - — - — - - - Create Win socket — - — — - - — — S = socket(AF_INET, SOCK_DGRAM, 0);//创建套接字 if(S == —1) ShowInfo(”socket_Create_Error\"); int l=sizeof(rAddr); char Msg[80]; puts(”Type exit then Quit Program!”); SetsockAddr(&lAddr, LPort, LIP);//初始化变量lAddr r = bind(S,(struct sockaddr far *)&lAddr, sizeof(lAddr)); if(r == —1) ShowInfo(\"bind_Error”); SetsockAddr(&rAddr, RPort, RIP); do{ //—— - - - - - — — Send Mess - — — - - — - — puts(”Send:\"); gets(Msg); if(!strcmp(Msg,”exit\"))// break; r = sendto(S,Msg,strlen(Msg), 0,(struct sockaddr far *)&rAddr, l);//通过套接字向接收端发送信息 if(r == —1) ShowInfo(\"Send_Error\"); //—— — — - — — — — Recieve Mess — — - — - — - — puts(”Send ok! Waiting Recieve.。.”); // r = recv(S, Msg, 80,0); r = recvfrom(S,Msg,80,0,(struct sockaddr far *)&rAddr, &l);// //发送套接口的主机地址信息存放在rAddr中 if(r == —1) ShowInfo(\"Recieve_Error\"); Msg[r]=0; puts(Msg); puts(\"Recieve ok!\"); }while(1); closesocket(S); WSACleanup(); return ; 9 计算机网络实验报告 Server端: #include ”stdafx.h\" #include WORD RPort = 7777; //远程端口RemotePort char RIP[16]=”127。0.0.1\"; //远程IP地址RemoteIPAddr WORD LPort = 6666; //本地端口LocalPort char LIP[16]=\"127.0。0.1”; //本地IP地址LocalIPAddr SOCKET S; //套接口SOCKET struct sockaddr_in rAddr; //远程参数,remoteAddr struct sockaddr_in lAddr; //本地参数,localAddr WSADATA WD; //Winsock DLL信息 int r; //result; //—-—-—----—----——--—--——-----——--—----—-—————--- void ShowInfo(char *info){ puts(info); exit(1); } //-—----—-—--—---———---————--——-—-——-—--———---—-- void SetsockAddr(struct sockaddr_in *A,WORD Port,char *IP){ A->sin_family = AF_INET; //TCP/IP协议 A—〉sin_port = htons(Port); //端口 A—〉sin_addr.s_addr =inet_addr(IP); //IP 地址 } //—--—---——--—-—-—----------—-——---——--—-—-—--——-— void main( ){ WORD v; //wVersionRequested; //—- - — - — - — — Startup Win socket - — — — — - - — v=0x0101; //0x0101 for v1.1, 0x0002 forv 2.0 r = WSAStartup(v, (LPWSADATA)&WD); if(r != 0) ShowInfo(”Start_Error”); //—- — — — - - — - Create Win socket - — - — - — - - S = socket(AF_INET, SOCK_DGRAM, 0);//创建套接字 if(S == —1) ShowInfo(”socket_Create_Error\"); int l=sizeof(rAddr); 10 计算机网络实验报告 char Msg[80]; puts(\"Type exit then Quit Program!\"); SetsockAddr(&lAddr, LPort, LIP);//初始化变量lAddr r = bind(S,(struct sockaddr far *)&lAddr, sizeof(lAddr)); if(r == —1) ShowInfo(”bind_Error\"); SetsockAddr(&rAddr, RPort, RIP); do{ //-— — - - - - — — Recieve Mess — - - — - — — - //puts(\"Send ok! Waiting Recieve。。.\"); //r = recv(S, Msg, 80,0); r = recvfrom(S,Msg,80,0,(struct sockaddr far *)&lAddr, &l);//发送套接口的主机地址信息存放在rAddr中 if(r == -1) ShowInfo(”Recieve_Error\"); Msg[r]=0; puts(Msg); puts(\"Recieve ok!\"); //-- — - - - — — — Send Mess - — — - — — — - puts(”Send:\"); gets(Msg); if(!strcmp(Msg,\"exit”))// break; r = sendto(S,Msg,strlen(Msg), 0,(struct sockaddr far *)&lAddr, l);//通过套接字向接收端发送信息 if(r == -1) ShowInfo(\"Send_Error”); }while(1); closesocket(S); WSACleanup(); return ; } 5.UDP通信程序数据结构的描述 (1)SOCKET S:服务器套接字 (2)struct sockaddr_in rAddr:远程参数,remoteAddr,存储TCP/IP协议,IP地址及端口号 (3)struct sockaddr_in lAddr:本地参数,localAddr,存储TCP/IP协议,IP地址及端口号 11 计算机网络实验报告 6.UDP通信程序的核心算法 服务器首先启动,通过调用socket( )建立一个套接口,然后bind( )将该套接口和本地地址(IP地址和端口)联系在一起,服务器调用recvfrom ( )等待接收数据。 客户机通过调用socket( )建立一个套接口,然后bind( )将该套接口和本地地址(IP地址和端口)联系在一起,客户机调用sendto( )向服务器发送数据; 服务器的recvfrom ( ) 接收到客户机的数据后,调用sendto( )向客户机发送应答数据; 客户机的recvfrom ( ) 便接收到了服务器的应答数据; 最后,待数据传送结束后,双方调用closesocket( )关闭套接口。 关于程序中调用的库函数的几点说明: 1. 对sendto函数的说明 int sendto( SOCKET s, //源套接口 char *buf, //待发送数据的缓冲区 int buflen, //缓冲区中数据的长度 int flags, //调用方式标志位,一般取0 struct sockaddr FAR *to, // 指向目的套接口的主机地址 int tolen //目的套接口主机地址的长度 ); sendto函数主要用于SOCK_DGRAM 类型套接口向to参数指定端的套接口发送数据报。对于SOCK_STREAM 类型套接口,to和tolen 参数被忽略;这种情况下sendto( ) 等价于send( ) 。 2. 对recvfrom函数的说明 int recvfrom( SOCKET s //接收套接口 char *buf //接收数据的缓冲区 int len //缓冲区中数据的长度 int flags //调用方式标志位,一般取0 struct sockaddr FAR *from // 获取发送套接口的主机地址 int fromlen //发送套接口的主机地址的长度 ); recvfrom函数主要用于从一个套接口接收数据 12 计算机网络实验报告 实验数据、结果分析 TCP通信程序实验结果分析: 当Client端启动时,Server端收到来自Client端的信号,表明双方的连接已经建立,可以互相通讯,从client端发送“hello”, Server端收到来自Client端的“hello”, Server端也可以向client端发送信息。 13 计算机网络实验报告 UDP通信程序实验结果分析: 打开UDP的client端,并打开UDP的server端,发送“hello”给server端,如下图所示:server端收到信息以后,发送“hi\"给client端,client端也能收到信息. 14 计算机网络实验报告 15 计算机网络实验报告 总结 16 因篇幅问题不能全部显示,请点此查看更多更全内容