UDP和TCP网络实验报告
- 格式:doc
- 大小:82.50 KB
- 文档页数:10
TCP和UDP客户端及服务器端实验报告一、原理1.基于TCP协议的服务器端程序流程:1)创建套接字(socket)2)绑定套接字(bind)3)将套接字设为监听,准备接收客户请求(listen)4)等待客户请求的到来,当请求到来后,接受请求,返回一个对应于此次连接的套接字(accept)5)用返回的套接字与客户端进行通信(send/recv)6)返回,等待另一客户请求7)关闭套接字2.基于TCP协议的客户端程序流程1)创建套接字(socket)2)向服务器发出连接请求(connect)3)和服务器端进行通信(send/recv)4)关闭套接字在服务器端调用accept函数时,程序就会等待客户端调用connect函数发出连接请求,然后接收请求,于是双方就建立了连接,之后,服务器端和客户端就可以利用send和recv函数进行通信了。
3.基于UDP的服务器端编写1)创建套接字(socket)2)绑定(bind)3)等待接收数据(recvfrom)4)关闭套接字4.基于UDP的客户端编写1)创建套接字(socket)2)向服务器发送数据(sendto)3)关闭套接字在所有的套接字编程中第一步都是加载套接字库(WSAStartup)对于每一个WSAStartup函数的成功调用,在最后都要对应一个WSACleanUp调用。
TCP代码实现:首先要建两个工程,不妨设为tcpsrv和tcpclient,分别为客户端和服务器端tcpsrv.cpp//TCP server//listen port 9102//receive string and display it//Visual C++ 6.0#include <stdio.h>#include <winsock2.h>#pragma comment(lib,"ws2_32.lib")#define BUFLEN 1024int main(){SOCKET serversoc;SOCKET clientsoc;SOCKADDR_IN serveraddr;SOCKADDR_IN clientaddr;char buf[BUFLEN];int len;WSADATA wsa;WSAStartup(MAKEWORD(1,1),&wsa);//initial Ws2_32.dll by a processif((serversoc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 0)//create a tcp socket {printf("Create socket fail!\n");return -1;}serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(9102);serveraddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);if(bind(serversoc, (SOCKADDR *)&serveraddr, sizeof(serveraddr)) != 0){printf("Bind fail!\n");return -1;}//start listen, maximum length of the queue of pending connections is 1printf("Start listen...\n");if(listen(serversoc, 1) != 0){printf("Listen fail!\n");return -1;}len = sizeof(SOCKADDR_IN);//waiting for connectingif((clientsoc = accept(serversoc, (SOCKADDR *)&clientaddr, &len))<=0) {printf("Accept fail!\n");return -1;}printf("Connected\n");while(1){//waiting for data receiveif(recv(clientsoc, buf, BUFLEN, 0) <= 0){//some error occurprintf("Close connection\n");closesocket(clientsoc);break;}printf("%s\n",buf);}WSACleanup(); //clean up Ws2_32.dllreturn 0;}相应的客户端程序,tcpclient.cpp//TCP client//client send string to server//Visual C++ 6.0#include <stdio.h>#include <winsock2.h>#pragma comment(lib,"ws2_32.lib")int main(){SOCKET soc;SOCKADDR_IN serveraddr;SOCKADDR_IN clientaddr;unsigned char buf[1024];WSADATA wsa;WSAStartup(MAKEWORD(1,1),&wsa);//initial Ws2_32.dll by a processif((soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 0)//create a tcp socket {printf("Create socket fail!\n");return -1;}serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(9102);serveraddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//connect to serverprintf("Try to connect...\n");if(connect(soc, (SOCKADDR *)&serveraddr, sizeof(serveraddr)) != 0){printf("Connect fail!\n");return -1;}printf("Connected\n");while(1){scanf("%s", buf);//send to serverif(send(soc, buf, strlen(buf)+1, 0)<=0){printf("Error!\n");}}WSACleanup(); //clean up Ws2_32.dllreturn 0;}UDP服务器端://UDP server//listen port 9102//receive string and display it//Visual C++ 6.0#include <stdio.h>#include <winsock2.h>#pragma comment(lib,"ws2_32.lib")#define BUFLEN 1024int main(void){SOCKET soc;SOCKADDR_IN addr;char buf[BUFLEN];int len;WSADATA wsa;WSAStartup(MAKEWORD(1,1),&wsa);//initial Ws2_32.dll by a process memset(&addr, 0, sizeof(addr));if((soc = socket(AF_INET,SOCK_DGRAM,0)) <= 0){printf("Create socket fail!\n");return -1;}addr.sin_family = AF_INET;addr.sin_port = htons(9102);addr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(soc,(struct sockaddr *)&addr,sizeof(struct sockaddr))!=0){printf("Bind fail!\n");return -1;}len = sizeof(addr);printf("start listen...\n");while(1) {recvfrom(soc, buf, BUFLEN, 0,(struct sockaddr*)&addr, &len);printf("%s\n",buf);}WSACleanup(); //关闭return 0;}客户端://UDP client//client send string to server//Visual C++ 6.0#include <stdio.h>#include <winsock2.h>#pragma comment(lib,"ws2_32.lib")#define BUFLEN 1024int main(void){SOCKET soc;SOCKADDR_IN addr;unsigned char buf[BUFLEN];WSADATA wsa;WSAStartup(MAKEWORD(2,2),&wsa);//initial Ws2_32.dll by a processmemset(&addr, 0, sizeof(addr));if((soc = socket(AF_INET,SOCK_DGRAM,0)) <= 0){printf("Create socket fail!\n");return -1;}addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr("127.0.0.1");addr.sin_port = htons(9102);bind(soc,(struct sockaddr *)&addr,sizeof(addr));while(1) {scanf("%s", buf);sendto(soc, buf, strlen(buf)+1, 0, (struct sockaddr *)&addr, sizeof(addr));}WSACleanup();//clean up Ws2_32.dllreturn 0;}。
实验报告课程计算机网络(双语)(课程设计)实验名称UDP及TCP通信程序的设计与实现专业班级姓名学号2013年 5 月30日目录实验目的和内容ﻩ错误!未定义书签。
实验目的ﻩ错误!未定义书签。
实验内容ﻩ错误!未定义书签。
实验环境ﻩ错误!未定义书签。
程序的逻辑框图ﻩ错误!未定义书签。
UDP通信程序的逻辑框图:ﻩ错误!未定义书签。
TCP通信程序的逻辑框图:ﻩ错误!未定义书签。
程序源代码(数据结构的描述、核心算法)ﻩ错误!未定义书签。
1.TCP通信程序源代码............................................. 错误!未定义书签。
2.TCP通信程序数据结构的描述ﻩ73.TCP通信程序的核心算法ﻩ错误!未定义书签。
4.UDP通信程序源代码.................................................. 错误!未定义书签。
5.UDP通信程序数据结构的描述.................................. 错误!未定义书签。
6.UDP通信程序的核心算法.......................................... 错误!未定义书签。
实验数据、结果分析.................................................................... 错误!未定义书签。
TCP通信程序实验结果分析ﻩ错误!未定义书签。
UDP通信程序实验结果分析......................................... 错误!未定义书签。
总结................................................................................................ 错误!未定义书签。
实验目的和内容实验目的掌握win32平台下,使用winsock API来实现UDP通信程序和TCP通信程序。
TCP协议与UDP协议分析实验(熟悉基础网络概念)一、实验目的1、理解TCP协议包格式和工作原理,如TCP建链拆链的三次握手机制和捎带应答机制等。
2、理解UDP协议包格式二、实验类型验证类实验三、实验课时2学时四、实验步骤1、在VC6.0以上环境下编译提供IPdump协议包分析程序,了解其工作原理和执行流程,重点熟悉TCP包解包函数和UDP包解包函数,然后运行该程序,并完成下列实验。
2、TCP协议分析●指定IPdump运行时源IP地址为主机A的地址,目的IP地址为主机B的地址,分析开关为TCP协议;●在主机B上启动TELNET服务,从主机A上向主机B发起telnet连接登陆到B上,并进行有关操作(如dir, cd / 等),然后退出telnet,捕获通信过程中的TCP数据包,记录并分析各字段的含义,并与TCP数据包格式进行比较;●在主机B上启动FTP服务,从主机A上向主机B发起FTP连接登陆到B上,并将A机的一个文件传输到B机上,然后退出ftp,捕获通信过程中的TCP数据包,记录并分析各字段的含义,并与TCP数据包格式进行比较;表2:FTP通信过程中的TCP包格式3、UDP 协议●指定IPdump运行时源IP地址为主机A的地址,目的IP地址为主机B的地址,分析开关为UDP协议;●在主机A的DOS仿真环境下,运行net send 命令向主机B发送一个UDP消息,捕获UDP数据包,记录并分析各字段的含义,并与UDP数据包格式进行比较;●在主机A的DOS仿真环境下,运行net send 命令向本网内所有主机发送一个UDP消息,捕获UDP数据包,记录并分析各字段的含义,并与UDP数据包格式进行比较;表3:UDP报文格式五、实验体会六、思考问题1、在两次TCP协议通信过程中,发送序列号是连续的吗,为什么在每次通信时发送序列号不从0开始编号呢?2、在主机A与主机B进行telnet通信时,从捕获的TCP包来看,在A上输入的命令是一个字符作为一个TCP包传送的还是一条命令作为一个TCP包传送的?为什么?。
实验报告课程计算机网络(双语)(课程设计)实验名称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个程序的源程序,程序代码有充分的注释,并填写实验报告,实验报告的主要内容为说明程序设计的思路,程序代码的流程。
实验环境在win7系统下,visual studio 2008环境下的win32平台下程序的逻辑框图UDP通信程序的逻辑框图:Server端:Client端:TCP通信程序的逻辑框图:Server端:程序源代码(数据结构的描述、核心算法)1.TCP通信程序源代码Client端:#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(){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协议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);//用于存储连接客户端的socketSOCKET 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中发送szTextsend(sClient, szText, strlen(szText), 0);//recv为阻塞函数,等待sClient中传来数据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;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 s3.TCP通信程序的核心算法服务器首先启动,通过调用socket( )建立一个套接口,然后bind( )将该套接口和本地地址(IP地址和端口)联系在一起,再listen( )使套接口做好侦听的准备,并规定它的请求队列的长度, 之后就调用accept( )来接收连接,并获得客户机的地址信息;客户在建立套接口后就可调用connect( ) 和服务器建立连接;连接一旦建立,客户机和服务器之间就可以通过调用:send( )和recv( ) (或read( )和write( ))来发送和接收数据;最后,待数据传送结束后,双方调用closesocket() 关闭套接口。
TCP协议分析实验报告
11300240047
马会心1 实验目的
用Wireshark分析TCP数据流和UDP数据流同时在网络传输时是如何占有所有可用带宽的,使学生对TCP协议的流量控制和拥塞控制有着较深的理解。
2 实验环境
Windows 7 Service Pack1
Wireshark Version 1.10.2
PCATTCP
3 实验内容
由于在机房抓取数据时,仅保留了数据包文件,而翻到实验指导书的最后一条才发现还需要cmd窗口的截图,所以只好在自己寝室的路由器局域网上重做了。
所以这里的IP地址等都与前面的实验不同。
3.1 两个TCP流的竞争
本节实验的数据包文件见tcp_tcp.pcapng。
本节实验中的命令行信息截图如下,其中端口5001的TCP流先被发送。
5001端口,发送方:
5001端口,接收方:
5002端口,发送方
5002端口,接收方
3.1.1 查看两个TCP流的情况
通过Wireshark中的TCP-Sequence Graph(tcptrace)功能,我们可以看到两个TCP流的整体传输情况。
(对于Flow Graph,我也尝试了一下,但感觉并不能很好的体现出TCP流的整体特性,所以没有涉及,下同)
两个TCP流的传输情况分别如下,前一张是先被发送的,后一张是延迟发送的。
TCPUDP协议分析实验TCP和UDP是网络传输中最常用的两个协议。
它们都属于传输层协议,但是在很多方面有着不同的特点和用途。
为了更好地理解这两个协议的工作原理和性能表现,我们可以进行一些实验来分析它们。
首先,我们可以比较TCP和UDP的连接建立过程。
TCP是一种面向连接的协议,连接的建立需要三次握手,而UDP是无连接的协议,不需要建立连接。
在实验中,我们可以编写一个客户端和一个服务器端来模拟TCP和UDP连接建立过程,并分析连接的建立时间和所占用的网络资源。
从实验结果可以看出,TCP的连接建立时间通常比UDP要长,因为它需要进行三次握手的过程来确保连接的可靠性,而UDP直接发送数据包,不进行握手过程。
其次,我们可以比较TCP和UDP在数据传输过程中的可靠性。
TCP是一种可靠的协议,它使用了序列号、确认应答和重传等机制来确保数据的可靠传输。
而UDP是一种不可靠的协议,它不会对数据进行检查和重传,只是简单地将数据发送给接收方。
在实验中,我们可以通过在网络中引入一些丢包或延迟的条件来模拟不同的网络环境,然后观察TCP和UDP的表现。
从实验结果可以看出,TCP在丢包或延迟的情况下仍能保证数据的可靠传输,而UDP在这种情况下可能会丢失一些数据。
另外,我们还可以比较TCP和UDP的传输效率。
TCP使用了拥塞控制和流量控制等机制来优化传输效率,但是也会因此增加了一些额外的开销。
而UDP没有这些机制,所以在传输效率方面可能会更高。
在实验中,我们可以通过在网络中增加一些流量或者限制带宽等条件来模拟不同的网络负载,并分析TCP和UDP的传输速度。
从实验结果可以看出,UDP在传输效率方面通常比TCP要高,但是也会因为没有拥塞控制而可能导致网络的拥堵。
最后,我们还可以比较TCP和UDP在不同应用场景下的适用性。
TCP 适用于对数据可靠性要求较高的应用,例如文件传输和网页浏览等。
而UDP适用于对实时性要求较高的应用,例如视频流和音频传输等。
实验六TCP和UDP数据分析一、实验目的深刻理解传输层协议的基本概念和工作原理,并可以通过该工具进行日常的网络诊断。
通过使用UDP 工具(Sender.exe)和TCP 工具(Telnet.exe 和netcat.exe)来与一些简单TCP/UDP 服务(echo、discard、daytime、qotd、chargen等服务器)的通讯,分析UDP、TCP协议的通讯过程。
通过netstat网络命令查看本机的网络链接状态,并从中分析网络状态。
二、实验环境多台具有Windows 操作系统的计算机、局域网环境,操作系统上安装有Ethereal软件。
并下载常用的网络工具。
三、实验内容1、Ethereal软件的安装(软件请从ftp://192.168.161.8下载)2、UDP数据包的抓取u 使用UDP Sender Receiver发送和接收数据包并抓取a) 普通发送b) 广播发送c) 多播发送d) 向UDP Echo 服务器发送数据包,并抓取返回的结果e) 向UDP Daytime 服务器发送数据包,并抓取返回的结果f) 向UDP Quote 服务器发送数据包,并抓取返回的结果g) 向UDP Chargen服务器发送数据包,并抓取返回的结果u 使用UDP Speed Test 发送和接收数据包,查看UDP数据的丢包情况3、TCP数据包的抓取u 使用Telnet 发送和接收数据包并抓取数据包a) 分析TCP 的连接建立、数据传输和释放过程,连接复位等,并通过netstat软件查看连接处于的状态。
b) 分析你在TCP连接中看到的TCP选项有哪些,有什么作用?c) 向一个没有开启服务的端口建立连接,看看TCP 是如何处理这种情况的d) 向TCP Echo 服务器发送数据包,并抓取返回的结果e) 向TCP Daytime 服务器发送数据包,并抓取返回的结果f) 向TCP Quote 服务器发送数据包,并抓取返回的结果g) 向TCP Chargen服务器发送数据包,并抓取返回的结果u 设计一些方法,如何通过netstat获得TCP连接分别处于LISTEN、SYN-RCVD 、SYN-SEND 、ESTABLISHED 、FIN-WAIT-1 、FIN-WAIT-2、TIME-WAIT等状态。
任务一:用Wireshark观察TCP连接的建立、使用和释放过程思考作业:a)浏览器进程的IP地址和端口号是什么?IP地址:192.168.209.44 端口号:3003b)服务器端进程的IP地址和端口号是什么?IP地址:128.119.245.12 端口号:80c)如何识别连接建立时的SYN报文,它的sequence序号值是多少?该TCP报文是从哪台主机发送出去的?通过查看图标中的中间绿色行,点显示SYN的箭头,可以识别。
Sequence序列号:0该TCP报文是从IP地址为192.168.209.44的主机发送出去d)如何识别SYN的确认报文,即SYN ACK,它是有哪台主机发送的?它的seqence序号值是什么?对SYN报文的确认号值是什么?确认后有什么样的含义?通过查看图标中的中间绿色行,点显示SYN ACK的箭头,可以识别。
它是从IP地址为128.119.245.12的主机发送的它的seqence序列号为0对SYN报文的确认号码为:1含义:1.表示已经受到报文2.表示愿意接受的下一个报文的序号e)观察前3个数据帧,它们是与TCP连接建立相关的数据,分析这些数据在TCP首部中的特点?确认TCP连接过程中协商的参数有哪些?TCP连接过程中的协商的参数有:源端口、目标端口、序号(Seq) 确认号(ACK)前提:观察TCP报文的可靠通信机制。
从第4个TCP报文开始(连接建立后的第一个),连续观察5个TCP报文的内容。
回答以下问题:a)每个TCP报文的长度值是多大?它们的最大值是多少?是否有确定依据?每个TCP报文的长度为617、0、1408、1408、1408。
他们的最大值为1408。
有确定依据。
b)每个TCP报文的序号值是什么?是否是连续变化?TCP报文的序号值:1 、618、1、2026、3434是连续变化的呈现不断增长的趋势c)每个TCP报文的确认号是什么?它的作用是什么?TCP报文的确认号:1、1、618、1、1它的作用:确认号表示愿意接受的下一个报文的序号,并表示成功接受该报文d)每个TCP报文首部中的Windows size是什么含义? 它的作用是什么?Windows size 是窗口大小的意思作用:TCP报文的流量控制由连接的每一端通过声明的窗口大小来提供e)连续的5个TCP报文是否有重传的现象?在此次跟踪中有重传的报文段。
TCP_UDP通信过程学习及实验报告[五篇]第一篇:TCP_UDP通信过程学习及实验报告1.当两台计算机分别和中继器、二层交换机、三层交换、路由器相连时,请分别画出计算机与交换设备五层参考模型;计算机A应用层计算机B应用层传输层传输层网络层网络层数据链路层数据链路层中继器物理层物理层物理层计算机A应用层计算机B应用层传输层传输层网络层二层交换机数据链路层网络层数据链路层数据链路层物理层物理层物理层计算机A应用层计算机B应用层传输层三层交换机网络层传输层网络层网络层数据链路层数据链路层数据链路层物理层物理层物理层计算机A应用层计算机B应用层传输层路由器网络层传输层网络层网络层数据链路层数据链路层数据链路层物理层物理层物理层2.学习SOCKET编程,写出TCP、UDP通信流程;将实例程序两个同学一组,实现两台计算机之间通信。
并写出学习报告;(a)TCP通信流程准备阶段:服务器程序首先进行初始化操作:(1)调用socket创建一个套接字(2)函数bind将这个套接字与服务器公认地址绑定在一起(3)函数listen将这个套接字转换成倾听套接字(listening socket)(4)调用函数accept来接受客户机的请求。
客户机程序初始化操作:(1)客户机调用函数socket创建一个套接字(2)调用函数connect 来与服务器建立连接。
连接建立之后,客户机与服务器通过读(read())、写(write())套接字来进行通信。
如下图:服务器端SocketTCP通信流程客户端bindSocketListenconnectwritesendsendwritecloseclose(b)UDP通信流程准备阶段:服务器程序首先进行初始化操作:(1)调用socket创建一个套接字(2)函数bind将这个套接字与服务器公认地址绑定在一起客户机程序初始化操作:(1)客户机调用函数socket创建一个套接字客户机与服务器通过读(sendto())、写(recvfrom())套接字来进行通信。
西安理工大学高科学院TCP\UDP程序开发实验报告姓名:专业:信息系统与信息管理班级:学号:日期:1:实验题目:基于UDP\TCP的聊天程序开发2:实验目的:开发TCP\UDP协议应用程序,掌握网络应用程序的工作原理。
通过本实验,深入理解TCP和UDP协议的异同点,了解网络协议的工作过程,学会网络通讯编程的基本方法,能够编制网络应用程序。
3.实验报告内容:(实验程序与注解如下)namespace ChatClient{using System;using ;using .Sockets;using System.Threading;using System.Text;public class Class1{//UDPClient对象private static UdpClient m_Client;//本地和远程端口private static int LocalPort = 8080;private static int RemotePort = 8080;//本地主机名称private static string m_szHostName;//广播组地址private static IPAddress m_GroupAddress;//远程广播组端private static IPEndPoint m_RemoteEP;//跟踪用户是否退出程序private static bool m_Done = false;//显示使用方法public static void Usage(){Console.WriteLine("UDP Multicast Chat Utility");Console.WriteLine("\nUsage:");Console.WriteLine("chat.exe");}public static void Initialize(){//初始化UDPClient对象m_Client = new UdpClient(LocalPort);//创建多目标广播组对象m_GroupAddress = IPAddress.Broadcast;//加入组m_Client.JoinMulticastGroup(m_GroupAddress);//创建远程广播组端m_RemoteEP = new IPEndPoint( m_GroupAddress, RemotePort); }public static void Terminate(){//退出广播组m_Client.DropMulticastGroup(m_GroupAddress);}public static void Listener(){//确保主线程开始接受用户输入Thread.Sleep(2000);//ASCII编码Encoding ASCII = Encoding.ASCII;//循环中不断接受数据while(!m_Done){IPEndPoint endpoint = null;//接受数据Byte[] data = m_Client.Receive(ref endpoint);//得到数据的ASCII字符串形式String strData = ASCII.GetString(data);//如果包含:@if( strData.IndexOf(":@") > 0 ){//先检查这个结束消息是否来自主线程还是来自其他聊天客户Char [] separators = {':'};String [] vars = strData.Split(separators);//如果是本地机器if( vars[0] == m_szHostName ){//结束线程Console.WriteLine("shutting down Listener thread...");//在这种情况下主线程已经把m_Done设为true,//这里为了保险起见,再次设置m_Done为truem_Done = true;}else{//显示消息,某个聊天客户已经离开Console.WriteLine("{0} has left the conversation", vars[0]); }}else{//如果这是一条聊天消息,则检查是否来自//本地机器,如果不是,则显示这条消息if(strData.IndexOf(":") > 0){Char [] separators = {':'};String [] vars = strData.Split(separators);if( vars[0] != m_szHostName ){Console.WriteLine(strData);}}}}Console.WriteLine("Listener thread finished...");return;}public static int Main( String [] args ){if( args.Length > 0 ){//显示使用方法信息Usage();return 1;}//得到主机名称和地址//m_szHostName = Dns.GetHostName(); IT超人m_szHostName = "127.0.0.1";//初始化Console.WriteLine("Initializing...");Initialize();Console.WriteLine("Starting Listener thread...");Thread t = new Thread(new ThreadStart(Listener));t.Start();//发送数据使用的缓冲区Byte [] buffer = null;//编码格式Encoding ASCII = Encoding.ASCII;//记录用户是否按下“@”键bool m_ShuttingDown = false;//循环语句中读取用户的输入并发送消息while(!m_ShuttingDown){String s = Console.ReadLine();//没有输入继续循环if( s.Length == 0 )continue;//如果第一个字母为@,则推出循环if(pare(s,0,"@",0,1) == 0){//停止监听线程中的循环m_Done = true;//向其他客户发送结束消息s = m_szHostName + ":@";m_ShuttingDown = true;}else{s = m_szHostName + ":" + s;}//分配发送缓冲区空间buffer = new Byte[s.Length + 1];//把字符串内容以ASCII编码格式放入发送缓冲区中int len = ASCII.GetBytes( s.ToCharArray(), 0, s.Length, buffer, 0);//发送消息int ecode = m_Client.Send(buffer, len, m_RemoteEP);//发送失败if(ecode <= 0){Console.WriteLine("Error in send : " + ecode);}}t.Abort();t.Join();namespace ChatClient{using System;using ;using .Sockets;using System.Threading;using System.Text;public class Class1{//UDPClient对象private static UdpClient m_Client;//本地和远程端口private static int LocalPort = 8080;private static int RemotePort = 8080;//本地主机名称private static string m_szHostName;//广播组地址private static IPAddress m_GroupAddress;//远程广播组端private static IPEndPoint m_RemoteEP;//跟踪用户是否退出程序private static bool m_Done = false;//显示使用方法public static void Usage(){Console.WriteLine("UDP Multicast Chat Utility"); Console.WriteLine("\nUsage:");Console.WriteLine("chat.exe");}public static void Initialize(){//初始化UDPClient对象m_Client = new UdpClient(LocalPort);//创建多目标广播组对象m_GroupAddress = IPAddress.Broadcast;//加入组m_Client.JoinMulticastGroup(m_GroupAddress);//创建远程广播组端m_RemoteEP = new IPEndPoint( m_GroupAddress, RemotePort); }public static void Terminate(){//退出广播组m_Client.DropMulticastGroup(m_GroupAddress);}public static void Listener(){//确保主线程接受用户输入Thread.Sleep(2000);//ASCII编码Encoding ASCII = Encoding.ASCII;//循环中不断接受数据while(!m_Done){IPEndPoint endpoint = null;//接受数据Byte[] data = m_Client.Receive(ref endpoint);//得到数据的ASCII字符串String strData = ASCII.GetString(data);//如果包含:@if( strData.IndexOf(":@") > 0 ){//先检查这个结束消息是否来自主线程还是来自其他聊天客户Char [] separators = {':'};String [] vars = strData.Split(separators);//如果是本地机器if( vars[0] == m_szHostName ){//结束线程Console.WriteLine("shutting down Listener thread...");//在这种情况下主线程已经把m_Done设为true,//这里为了保险起见,再次设置m_Done为truem_Done = true;}else{//显示消息,某个客户已下线Console.WriteLine("{0} has left the conversation", vars[0]);}}else{//如果这是一条聊天消息,则检查是否来自//本地机器,如果不是,则显示这条消息if(strData.IndexOf(":") > 0){Char [] separators = {':'};String [] vars = strData.Split(separators);if( vars[0] != m_szHostName ){Console.WriteLine(strData);}}}}Console.WriteLine("Listener thread finished...");return;}public static int Main( String [] args ){if( args.Length > 0 ){//显示使用方法信息Usage();return 1;}//得到主机名称和地址//m_szHostName = Dns.GetHostName(); 123m_szHostName = "127.0.0.1";//初始化Console.WriteLine("Initializing...");Initialize();//开始监听Console.WriteLine("Starting Listener thread...");Thread t = new Thread(new ThreadStart(Listener)); t.Start();//发送数据使用的缓冲区Byte [] buffer = null;//编码格式Encoding ASCII = Encoding.ASCII;//记录用户是否按下“@”键bool m_ShuttingDown = false;//循环语句中读取用户的输入并发送消息while(!m_ShuttingDown){String s = Console.ReadLine();//没有输入继续循环if( s.Length == 0 )continue;//如果第一个字母为@,则推出循环if(pare(s,0,"@",0,1) == 0){//停止监听线程中的循环m_Done = true;//向其他客户发送结束消息s = m_szHostName + ":@";m_ShuttingDown = true;}else{s = m_szHostName + ":" + s;}//分配发送缓冲区空间buffer = new Byte[s.Length + 1];int len = ASCII.GetBytes( s.ToCharArray(), 0, s.Length, buffer,0);//发送int ecode = m_Client.Send(buffer, len, m_RemoteEP);//发送失败if(ecode <= 0){Console.WriteLine("Error in send : " + ecode);}}//结束监听t.Abort();t.Join();//中断连接Console.WriteLine("Closing connection...");Terminate();return 0;}}}程序结束4系统测试:通过单机和联机状态下的实验,本程序基本达到了实验目的的要求。