计算机网络原理实验七、传输层可靠传输协议GBN编程实验报告
计算机网络原理实验七实验报告
![计算机网络原理实验七实验报告](https://img.taocdn.com/s3/m/a14ea23d3069a45177232f60ddccda38376be179.png)
计算机⽹络原理实验七实验报告实验七、传输层可靠传输协GBN编程实验报告序号:姓名:学号:成绩指导⽼师:⼀、实验⽬的:1、通过编写实现⼀个简单可靠的数据传输协议GBN的发送和接收代码,模拟可靠数据传输2、理解TCP协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
⼆、实验指导:参考教材。
三、实验要求:编程实现⼀个GBN传输协议的发送⽅和接收⽅两程序,采⽤编程语⾔不限,要求能将发送――接收流程以及处理⽅法表现出来.附源代码及注释通过本次实验,了解了GBN传输协议的相关知识,因为实验代码是由三部分组成,所以⽤Studio做实验时,要建⽴3个⽂件,⼀个是头⽂件,存放gbn.h, 另外2个是源⽂件,分别存放gbn.c 和 gbn-cs.c,然后再启动调试。
实验代码通过查阅资料很容易理解,但是怎么实现这个程序对我来说是个问题。
后来我把程序分了3部分,⼀个头⽂件和两个源⽂件,通过visual studio可以良好的运⾏,以下为⽼师附带代码的运⾏结果⼀、GBN.h#pragma once#include//基础功能模块的数据结构声明#define BIDIRECTIONAL 1 /* change to 1 if you're doing extra credit and write a routine called B_output *//* a "msg" is the data unit passed from layer 5 (teachers code) to layer4 (students' code). It contains the data (characters) to be delivered tolayer 5 via the students transport level protocol entities. */ struct msg{ char data[20];};/* a packet is the data unit passed from layer 4 (students code) to layer3 (teachers code). Note the pre-defined packet structure, which allstudents must follow. */struct pkt{int seqnum;int acknum;int checksum;char payload[20];};#define WINDOWSIZE 8#define MAXBUFSIZE 50#define RTT 15.0#define NOTUSED 0#define NACK -1#define TRUE 1#define FALSE 0#define A 0#define B 1//⽹络仿真部分数据结构声明***********************************************************struct event{float evtime; /* event time */int evtype; /* event type code */int eventity; /* entity where event occurs */struct pkt *pktptr; /* ptr to packet (if any) assoc w/ this event */ struct event *prev;struct event *next;};/* possible events: */#define TIMER_INTERRUPT 0#define FROM_LAYER5 1#define FROM_LAYER3 2#define OFF 0#define ON 1//基础功能模块的函数声明******************************************************************* void ComputeChecksum(struct pkt *packet);//计算校验和int CheckCorrupted(struct pkt packet);//检查数据是否出错void A_output( struct msg message);//A端向外发送数据void A_input(struct pkt packet);//A端接收数据void A_timerinterrupt();//A计时器超时void A_init();//A端初始化void B_output(struct msg message);void B_input(struct pkt packet);void B_timerinterrupt();void B_init();//⽹络仿真部分的函数声明**************************************************void init(); //初始化仿真器float jimsrand();//随机数发⽣器[0,1]//处理事件列表部分的函数声明*********************************************void generate_next_arrival();//产⽣下⼀个到达的分组void insertevent(struct event *p);//向事件列表中插⼊⼀条新的事件void printevlist();//打印事件列表//******************************************************************** //**********************计时器模块*********************************** void stoptimer(int);//停⽌计时器void starttimer(int,float);//启动计时器//******************************************************************** *//**************************⽹络各层之间传送模块***********************void tolayer3(int AorB,struct pkt packet);//向第3层发送信息void tolayer5(int AorB,char datasent[20]);//向第5层发送信息⼆、GBN.c#include "GBN.h"#include#include#includeextern int TRACE = 1; /* for my debugging */extern int nsim = 0; /* number of messages from 5 to 4 so far */extern int nsimmax = 0; /* number of msgs to generate, then stop */extern float time = 0.000;float lossprob; /* probability that a packet is dropped */ float corruptprob; /* probability that one bit is packet is flipped */ float lambda; /* arrival rate of messages from layer 5 */ int ntolayer3; /* number sent into layer 3 */static int nlost = 0; /* number lost in media */static int ncorrupt = 0; /* number corrupted by media*/static int expectedseqnum = 0; /* expected sequence number at receiver side */static int nextseqnum; /* next sequence number to use in sender side */static int base; /* the head of sender window */struct pkt winbuf[WINDOWSIZE]; /* window packets buffer */static int winfront,winrear; /* front and rear points of window buffer */static int pktnum; /* packet number of window buffer */struct msg buffer[MAXBUFSIZE]; /* sender message buffer */int buffront,bufrear; /* front and rear pointers of buffer */ static int msgnum; /* message number of buffer */int packet_lost =0;int packet_corrupt=0;int packet_sent =0;extern int packet_correct=0;extern int packet_resent =0;int packet_timeout=0;extern struct event *evlist = NULL; /* the event list *///计算校验和void ComputeChecksum( struct pkt *packet){int checksum;int i;checksum = packet->seqnum;checksum = checksum + packet->acknum;for ( i=0; i<20; i++ )checksum = checksum + (int)(packet->payload[i]);checksum = 0-checksum;packet->checksum = checksum;}//检查是否出错int CheckCorrupted(struct pkt packet){int checksum;int i;checksum = packet.seqnum;checksum = checksum + packet.acknum;for ( i=0; i<20; i++ )checksum = checksum + (int)(packet.payload[i]);if ( (packet.checksum+checksum) == 0 )return (FALSE);elsereturn (TRUE);}//A端向外发送数据/* called from layer 5, passed the data to be sent to other side */ void A_output(struct msg message){int i;struct pkt sendpkt;/* if window is not full */if ( nextseqnum < base+WINDOWSIZE ){printf("----A: New message arrives, send window is not full, send new messge to layer3!\n"); /* create packet */sendpkt.seqnum = nextseqnum;sendpkt.acknum = NOTUSED;for ( i=0; i<20 ; i++ )sendpkt.payload[i] = message.data[i];/* computer checksum */ComputeChecksum (&sendpkt);/* send out packet */tolayer3 (A, sendpkt);/* copy the packet to window packet buffer */winrear = (winrear+1)%WINDOWSIZE;pktnum ++;winbuf[winrear] = sendpkt;for (i=0; i<20; i++)winbuf[winrear].payload[i]= sendpkt.payload[i];/* update state variables */nextseqnum = nextseqnum+1;starttimer(A,RTT);B_input(sendpkt);A_input(sendpkt);}/* if window is full */else{printf("----A: New message arrives, send window is full,");/* if buffer full, give up and exit*/if ( msgnum == MAXBUFSIZE){printf (" Error: Sender buffer is full! \n");exit (1);}/* otherwise, buffer the message */else{printf("buffer new message!\n");bufrear = (bufrear+1) % MAXBUFSIZE;for (i=0; i<20; i++)buffer[bufrear].data[i] = message.data[i];msgnum ++;}}}//B端向外发送数据/* called from layer 5, passed the data to be sent to other side */ void B_output(struct msg message) {int i;struct pkt sendpkt;/* if window is not full */if ( nextseqnum < base+WINDOWSIZE ){printf("----A: New message arrives, send window is not full, send new messge to layer3!\n");/* create packet */sendpkt.seqnum = nextseqnum;sendpkt.acknum = NOTUSED;for ( i=0; i<20 ; i++ )sendpkt.payload[i] = message.data[i];/* computer checksum */ComputeChecksum (&sendpkt);/* send out packet */tolayer3 (A, sendpkt);A_input(sendpkt);/* copy the packet to window packet buffer */winrear = (winrear+1)%WINDOWSIZE;pktnum ++;winbuf[winrear] = sendpkt;for (i=0; i<20; i++)winbuf[winrear].payload[i]= sendpkt.payload[i];/* if it is the first packet in window, start timeout */ //if ( base == nextseqnum ) //{//starttimer(A,RTT);//printf("----A: start a new timer!\n");// }/* update state variables */nextseqnum = nextseqnum+1;}/* if window is full */else{printf("----A: New message arrives, send window is full,");/* if buffer full, give up and exit*/if ( msgnum == MAXBUFSIZE){printf (" Error: Sender buffer is full! \n");exit (1);}/* otherwise, buffer the message */else{printf("buffer new message!\n");bufrear = (bufrear+1) % MAXBUFSIZE;for (i=0; i<20; i++)buffer[bufrear].data[i] = message.data[i];msgnum ++;}}}//A端接收数据void A_input(struct pkt packet){struct pkt sendpkt;int i;/* if received packet is not corrupted and ACK is received */if ( (CheckCorrupted(packet) == FALSE) && (packet.acknum != NACK) ) {printf("----A: ACK %d is correctly received,",packet.acknum);packet_correct++;/* delete the acked packets from window buffer */winfront = (winfront+(packet.acknum+1-base)) % WINDOWSIZE; pktnum = pktnum - (packet.acknum+1-base); /* move window base */base = packet.acknum+1;stoptimer(A);if ( base < nextseqnum){//starttimer(A,RTT);printf ("\n\n\nsend new packets!");}/* if buffer is not empty, send new packets */while ( (msgnum!=0) && (nextseqnum/* create packet */sendpkt.seqnum = nextseqnum;sendpkt.acknum = NOTUSED;buffront = (buffront+1) % MAXBUFSIZE;for ( i=0; i<20 ; i++ )sendpkt.payload[i] = buffer[buffront].data[i];/* computer checksum */ComputeChecksum (&sendpkt);/* if it is the first packet in window, start timeout */ if ( base == nextseqnum ){//starttimer(A,RTT);printf ("send new packets!\n");}/* send out packet */tolayer3 (A, sendpkt);/* copy the packet to window packet buffer */winrear = (winrear+1)%WINDOWSIZE;winbuf[winrear] = sendpkt;pktnum ++;/* update state variables */nextseqnum = nextseqnum+1;/* delete message from buffer */msgnum --;}}elseprintf ("----A: NACK is received, do nothing!\n");}//B端接收数据*****************************************************⼀定要调⽤这个/* Note that with simplex transfer from a-to-B, there is no B_output() */ /* called from layer 3, when a packet arrives for layer 4 at B*/void B_input(struct pkt packet){struct pkt sendpkt;int i;/* if not corrupted and received packet is in order */if ( (CheckCorrupted(packet) == FALSE) && (packet.seqnum == expectedseqnum)){printf("\n----B: packet %d is correctly received, send ACK!\n",packet.seqnum);/* send an ACK for the received packet *//* create packet */sendpkt.seqnum = NOTUSED;sendpkt.acknum = expectedseqnum;for ( i=0; i<20 ; i++ )sendpkt.payload[i] = '0';/* computer checksum */ComputeChecksum (&sendpkt);/* send out packet *///tolayer3 (B, sendpkt);/* update state variables */expectedseqnum = expectedseqnum+1;printf("----B:expectedseqnum = %d\n",expectedseqnum);/* deliver received packet to layer 5 *///tolayer5(B,packet.payload);}/* otherwise, discard the packet and send a NACK */else{printf("----B: packet %d is corrupted or not I expects, send NACK!\n",packet.seqnum); /* create packet */sendpkt.seqnum = NOTUSED;sendpkt.acknum = NACK;for ( i=0; i<20 ; i++ )sendpkt.payload[i] = '0';/* computer checksum */ComputeChecksum (&sendpkt);/* send out packet */tolayer3 (B, sendpkt);}}//A计时器超时/* called when A's timer goes off */void A_timerinterrupt(){int i;printf("----A: time out,resend packets!\n");/* start timer */starttimer(A,RTT);/* resend all packets not acked */for ( i=1; i<=pktnum; i++ ){packet_resent++;tolayer3(A,winbuf[(winfront+i)%WINDOWSIZE]);}}//B计时器超时/* called when B's timer goes off */void B_timerinterrupt(){int i;printf("----B: time out,resend packets!\n");/* start timer */starttimer(B,RTT);/* resend all packets not acked */for ( i=1; i<=pktnum; i++ ){packet_resent++;tolayer3(B,winbuf[(winfront+i)%WINDOWSIZE]);}}//A端初始化/* entity A routines are called. You can use it to do any initialization */ void A_init(){base = 0;nextseqnum = 0;buffront = 0;bufrear = 0;msgnum = 0;winfront = 0;winrear = 0;pktnum = 0;}//B端初始化/* entity B routines are called. You can use it to do any initialization */ void B_init(){expectedseqnum = 0;}//初始化仿真器void init() /* initialize the simulator */{int i;float sum, avg;float jimsrand();FILE *fp;fp = fopen ("parameter.txt","r");printf("----- Stop and Wait Network Simulator Version 1.1 -------- \n\n");printf("Enter the number of messages to simulate: ");//fscanf(fp,"%d",&nsimmax);scanf("%d",&nsimmax);printf("\nEnter packet loss probability [enter 0.0 for no loss]: "); //fscanf(fp, "%f",&lossprob);scanf("%f",&lossprob);printf("\nEnter packet corruption probability [0.0 for no corruption]: "); //fscanf(fp,"%f",&corruptprob);scanf("%f",&corruptprob);printf("\nEnter average time between messages from sender's layer5 [ > 0.0]: ");//fscanf(fp,"%f",&lambda);scanf("%f",&lambda);printf("\nEnter TRACE: ");//fscanf(fp,"%d",&TRACE);scanf("%d",&TRACE);printf("\n\n");srand(9999); /* init random number generator */sum = 0.0; /* test random number generator for students */for (i=0; i<1000; i++)sum=sum+jimsrand(); /* jimsrand() should be uniform in [0,1] */avg = sum/1000.0;/*if(avg < 0.25 || avg > 0.75){printf("It is likely that random number generation on your machine\n" ); printf("is different from what this emulator expects. Please take\n"); printf("a look at the routine jimsrand() in the emulator code. Sorry. \n");exit(0);}*/printf("%f",avg);ntolayer3 = 0;nlost = 0;ncorrupt = 0;time=0.0; /* initialize time to 0.0 */generate_next_arrival(); /* initialize event list */}//随机数发⽣器float jimsrand(){double mmm = 2147483647; /* largest int - MACHINE DEPENDENT */ float x; /* individual students may need to change mmm */x = rand()/mmm; /* x should be uniform in [0,1] */return(x);}//**************************************************************************************//*******************************事件处理部分*******************************************void generate_next_arrival(){double x,log(),ceil();struct event *evptr;float ttime;int tempint;//if (TRACE>2)//printf("-----------------GENERATE NEXT ARRIVAL: creating new arrival\n"); x = lambda*jimsrand()*2; /* x is uniform on [0,2*lambda] *//* having mean of lambda */evptr = (struct event *)malloc(sizeof(struct event));evptr->evtime = time + x;evptr->evtype = FROM_LAYER5;if (jimsrand()<0.5){evptr->eventity = A;}elseevptr->eventity = B;insertevent(evptr);}//向事件列表中插⼊⼀条新的事件void insertevent(struct event *p){struct event *q,*qold;if (TRACE>2){//printf(" INSERTEVENT: time is %lf\n",time);//printf(" INSERTEVENT: future time will be %lf\n",p->evtime);}q = evlist; /* q points to front of list in which p struct inserted */if (q==NULL)/* list is empty */{evlist=p;p->next=NULL;p->prev=NULL;}else{for (qold = q; q !=NULL && p->evtime > q->evtime; q=q->next) qold=q; if (q==NULL)/* end of list */{qold->next = p;p->prev = qold;p->next = NULL;}else if (q==evlist)/* front of list */{p->next=evlist;p->prev=NULL;p->next->prev=p;evlist = p;}else /* middle of list */{p->next=q;p->prev=q->prev;q->prev->next=p;q->prev=p;}}}//打印事件列表void printevlist(){struct event *q;int i;printf("--------------\nEvent List Follows:\n");for(q = evlist; q!=NULL; q=q->next){printf("Event time: %f, type: %d entity: %d\n",q->evtime,q->evtype,q->eventity); }printf("--------------\n");}//启动计时器void starttimer(int AorB,float increment){struct event *q;struct event *evptr;。
网络层协议实验报告(3篇)
![网络层协议实验报告(3篇)](https://img.taocdn.com/s3/m/62f7dc16a517866fb84ae45c3b3567ec112ddc6f.png)
第1篇一、实验目的1. 理解网络层协议的基本概念和作用;2. 掌握IP协议、ARP协议和RIP协议的基本原理和配置方法;3. 通过实验验证网络层协议在实际网络中的应用。
二、实验环境1. 实验设备:一台安装有Cisco Packet Tracer软件的PC机;2. 实验软件:Cisco Packet Tracer 7.3.1模拟器;3. 实验拓扑:实验拓扑结构如图1所示,包括三台路由器(R1、R2、R3)和三台主机(H1、H2、H3)。
图1 实验拓扑结构图三、实验内容1. IP协议分析实验(1)实验目的:了解IP协议的基本原理和配置方法。
(2)实验步骤:① 在R1、R2、R3上配置IP地址、子网掩码和默认网关;② 在H1、H2、H3上配置IP地址、子网掩码和默认网关;③ 使用Ping命令测试H1与H2、H3之间的连通性;④ 分析实验结果,验证IP协议在网络层的作用。
(3)实验结果与分析:通过实验,验证了IP协议在网络层中实现数据包的传输和路由功能。
当H1与H2、H3之间进行通信时,数据包会按照IP地址进行路由,最终到达目标主机。
2. ARP协议分析实验(1)实验目的:了解ARP协议的基本原理和配置方法。
(2)实验步骤:① 在R1、R2、R3上配置IP地址、子网掩码和默认网关;② 在H1、H2、H3上配置IP地址、子网掩码和默认网关;③ 在H1上配置MAC地址与IP地址的静态映射;④ 使用Ping命令测试H1与H2、H3之间的连通性;⑤ 分析实验结果,验证ARP协议在网络层的作用。
(3)实验结果与分析:通过实验,验证了ARP协议在网络层中实现IP地址与MAC地址的映射功能。
当H1与H2、H3之间进行通信时,数据包会通过ARP协议获取目标主机的MAC地址,从而实现数据包的传输。
3. RIP协议分析实验(1)实验目的:了解RIP协议的基本原理和配置方法。
(2)实验步骤:① 在R1、R2、R3上配置IP地址、子网掩码和默认网关;② 在R1、R2、R3上配置RIP协议,使其相互通告路由信息;③ 在H1、H2、H3上配置IP地址、子网掩码和默认网关;④ 使用Ping命令测试H1与H2、H3之间的连通性;⑤ 分析实验结果,验证RIP协议在网络层的作用。
计算机网络原理实验七传输层可靠传输协议GBN编程实验报告精编
![计算机网络原理实验七传输层可靠传输协议GBN编程实验报告精编](https://img.taocdn.com/s3/m/22692261e3bd960590c69ec3d5bbfd0a7956d580.png)
计算机网络原理实验七传输层可靠传输协议GBN编程实验报告精编实验七:传输层可靠传输协议-GBN编程实验报告一、实验目的1. 理解传输层的可靠传输协议GBN(Go-Back-N)的工作原理;2. 利用Python编程实现GBN协议;3.通过实验验证GBN协议的可靠性。
二、实验环境1. 操作系统:Windows 10;2. 开发工具:Python3.9;3. Python库:socket, threading。
三、实验原理GBN(Go-Back-N)协议是一种滑动窗口协议,用于实现可靠的传输。
在GBN协议中,发送方可以连续发送一批数据包,每个数据包都有一个序号。
接收方会按照相同的序号顺序接收并确认收到的数据包,若一些数据包丢失,则接收方会等待一定时间,然后要求发送方重传从丢失的数据包开始之后的所有数据包。
在本实验中,我们将通过编程实现一个简化的GBN协议。
发送方和接收方将通过socket进行通信。
发送方将发送一定数量的数据包,接收方将模拟数据包丢失,并且在一段时间后要求发送方重传。
四、实验过程1. 建立发送方和接收方的socket连接,并互相绑定IP地址和端口号;2.发送方将一定数量的数据包发送给接收方;3.接收方按照GBN协议的规定接收数据包,并发送确认信息给发送方;4.发送方接收到确认信息后,继续发送下一批数据包;5.当接收方丢失数据包时,等待一段时间之后要求发送方重传;6.发送方收到重传请求后,重新发送从丢失的数据包开始之后的所有数据包;7.重复步骤2-6,直到所有数据包都被成功接收。
五、实验结果经过多次实验,数据包的发送与接收均顺利进行。
发送方能够根据接收方的确认信息进行滑动窗口的滑动,并实现重传功能。
接收方也能够检测到丢失的数据包,并要求发送方进行重传。
整个传输过程基本完成了GBN协议可靠性传输的要求。
六、实验总结通过本次实验,我深入理解了传输层的可靠传输协议GBN的工作原理,并通过编程实现了一个简化的GBN协议。
实验五、传输层可靠传输协议GBN编程实验报告
![实验五、传输层可靠传输协议GBN编程实验报告](https://img.taocdn.com/s3/m/62f13438bdd126fff705cc1755270722192e59c8.png)
实验五、传输层可靠传输协议GBN编程实验报告序号:姓名:杨学号:成绩一、实验目的:1、编程实现简单可靠的数据传输GBN协议,模拟可靠数据传输2、理解TCP协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
二、实验指导:参考教材。
三、实验要求:编程实现一个GBN传输协议,程序源代码:发送方源代码:// sender.cpp发送方程序代码,定义控制台应用程序的入口点//#include <stdafx.h>#include <iostream>#include <WinSock2.h>#include <string.h>#include <../header/ARQ.h>#include <../header/Exception.h>#define SERVER_PORT 2011 // 服务器端口#define MAXRETRY 5 //最大重传次数#define TIMEOUT 2000 // 传送传时时间#pragma comment(lib,"ws2_32.lib")//设置link时的lib库using namespace std;SOCKET PrimaryUDP;char ServerIP[20];char FilePath[MAX_PATH];bool g_number = false; // 用作奇偶检校的序号char g_bcc;// 返回的控制字符HANDLE m_hEvent;void InitWinSock(){WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){throw Exception("Windows sockets 2.2 startup unsuccessful");}else{printf("Using %s (Status: %s)\n",wsaData.szDescription, wsaData.szSystemStatus);printf("with API versions %d.%d to %d.%d\n\n",LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));}}void mksock(int type){PrimaryUDP = socket(AF_INET, type, 0);if (PrimaryUDP < 0){throw Exception("create socket error");}}void BindSock(){sockaddr_in sin;sin.sin_addr.S_un.S_addr = INADDR_ANY;sin.sin_family = AF_INET;sin.sin_port = 0;if (bind(PrimaryUDP, (struct sockaddr*)&sin, sizeof(sin)) < 0) throw Exception("bind error");}bool ASendto(){sockaddr_in remote;remote.sin_addr.S_un.S_addr = inet_addr(ServerIP);remote.sin_family = AF_INET;remote.sin_port = htons(SERVER_PORT);int fromlen = sizeof(remote);// 打开文件FILE * file;if((file = fopen(FilePath, "rb")) == NULL){cout<<FilePath<<" open error"<<endl;return false;}cout<<"file open succeed"<<endl;// 设置文件指针位置SetFilePointer(file, 0, NULL, FILE_BEGIN);BSC bsc;bsc.header = STX;bsc.tail = ETX;// 设为有信号SetEvent(m_hEvent);// 分段序号bool number = false;unsigned long dwRead = -1;bool sendComplete = false;while(!sendComplete){// 清空数据memset(bsc.data, 0, MAXBSCLENGTH);// 当前分块的奇偶序号bsc.number=number;// 记录当前的分块序号g_number = bsc.number;if (dwRead ==-1)//第一次应发送文件请求消息{// 发送文件请求bsc.bcc = ENQ;char * filename = FilePath;if ((filename = strrchr(FilePath,'\\'))==NULL)filename = FilePath;else++filename;strcpy(bsc.data,filename);dwRead = 0;}else{if(!feof(file)){bsc.bcc = SYN;int i = fread(bsc.data, sizeof(char),MAXBSCLENGTH , file);cout<<"read:"<<i<<"\tsend:"<<sizeof(bsc.data)<<endl;dwRead+=i;}else{// 发送完毕bsc.bcc = EOT;sendComplete = true;cout<<"send complete.send size:"<<dwRead<<endl;fclose(file);}}for(int i=0;i<MAXRETRY;i++){sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,fromlen);ResetEvent(m_hEvent);DWORD reslut = WaitForSingleObject(m_hEvent,TIMEOUT);if (reslut == WAIT_OBJECT_0){// 收到应答消息,一种是ACK,一种是NAKif (g_bcc == NAK){if (i == MAXRETRY -1){return false;}// 继续重传continue;}else{ // 收到应答消息//cout<<"send succeed"<<endl;break;}}else if(i == MAXRETRY-1){cout<<"send file failed"<<endl;return false;}} // 开始发下一段数据number = !number;}return true;}DWORD WINAPI ARecv(LPVOID lpParam){sockaddr_in remote;int sinlen = sizeof(remote);BSC buffer;int iread = 0;while (true){iread = recvfrom(PrimaryUDP,(char*)&buffer,sizeof(buffer),0,(sockaddr*)&remote,&sinlen);// 处理ACK与NAKif (iread == SOCKET_ERROR){continue;}// 与当前的分块序号进行比较,看是不是当前块的应答if (buffer.number!=g_number){continue;}if (buffer.bcc == ACK || buffer.bcc == NAK){// 保存返回的控制字符g_bcc = buffer.bcc;SetEvent(m_hEvent);}}return 0;}int _tmain(int argc, _TCHAR* argv[]){InitWinSock();mksock(SOCK_DGRAM);BindSock();cout<<"Please input receiver ip:";cin>>ServerIP;cout<<"Please input the file path:";cin>>FilePath;m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);CreateThread(NULL, 0, ARecv, NULL, 0, NULL);if (!ASendto()){cout<<"file send failed"<<endl;getchar();}getchar();getchar();return 0;}接收方源代码:// receiver.cpp 接收方程序代码,定义控制台应用程序的入口点// #include <stdafx.h>#include <iostream>#include <WinSock2.h>#include <../header/ARQ.h>#include <../header/Exception.h>#define SERVER_PORT 2011// 服务器端口#pragma comment(lib,"ws2_32.lib")//设置link时的lib库using namespace std;SOCKET PrimaryUDP;char FileSavePath[MAX_PATH];void InitWinSock(){WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){throw Exception("Windows sockets 2.2 startup unsuccessful");}else{printf("Using %s (Status: %s)\n",wsaData.szDescription, wsaData.szSystemStatus);printf("with API versions %d.%d to %d.%d\n\n",LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));}}void mksock(int type){PrimaryUDP = socket(AF_INET, type, 0);if (PrimaryUDP < 0){throw Exception("create socket error");}}void BindSock(){sockaddr_in sin;sin.sin_addr.S_un.S_addr = INADDR_ANY;sin.sin_family = AF_INET;sin.sin_port = htons(SERVER_PORT);if (bind(PrimaryUDP, (struct sockaddr*)&sin, sizeof(sin)) < 0) throw Exception("bind error");}DWORD WINAPI ARecv(LPVOID lpParam){FILE * file = NULL;sockaddr_in remote;int sinlen = sizeof(remote);BSC buffer,bsc;bsc.header = STX;bsc.tail = ETX;memset(bsc.data, 0, MAXBSCLENGTH);int iread = 0;unsigned long dwReceived = 0;bool number = true;//发送方的数据开始发送时的序号设为0,为了判断是不是第一次一段数据,所以这里标为1while (true){iread = recvfrom(PrimaryUDP,(char*)&buffer,sizeof(buffer),0,(sockaddr*)&remote,&sinlen) ;if (SOCKET_ERROR == iread || buffer.header != STX || buffer.tail != ETX) {// 数据错误,发送负应答cout<<"received a error data"<<endl;bsc.bcc = NAK;bsc.number=false;//number这时没有实际的意义sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);continue;}if (buffer.number == number){// 重复收到数据,发送应答消息cout<<"received a repeat data"<<endl;bsc.bcc = ACK;bsc.number = buffer.number;sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);continue;}switch(buffer.bcc){case ENQ:{number = !number;//准备接收下一段数据// 文件请求cout<<"received a file request message,filename:"<<buffer.data<<endl;// 打开文件if(strcmp((FileSavePath+strlen(FileSavePath)-1),"\\")!=0)strcat(FileSavePath,"\\");strcat(FileSavePath,buffer.data);if((file = fopen(FileSavePath, "ab")) == NULL){cout<<"file open failed"<<endl;return -1;}break;}case SYN:{number = !number;// 文字发送中int i =0;if((i=fwrite(buffer.data, sizeof(char), sizeof(buffer.data), file)) <= 0){cout << "write failed" << endl;return -1;}dwReceived += i;cout<<"write:"<<i<<"\treceived:"<<sizeof(buffer.data)<<endl;break;}case EOT:{number = !number;// 文件发送完毕cout<<"file received completely,save path:"<<FileSavePath<<",received size:"<<dwReceived<<endl;fclose(file);break;}default:{// 数据错误,发送负应答bsc.bcc = NAK;bsc.number=false;sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);continue;break;}} // 发送应答消息bsc.bcc = ACK;bsc.number = buffer.number;sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);}return 0;}int _tmain(int argc, _TCHAR* argv[]){InitWinSock();mksock(SOCK_DGRAM);BindSock();CreateThread(NULL, 0, ARecv, NULL, 0, NULL);cout<<"Please input the file save path:";cin>>FileSavePath;cout<<"receiver start succeed"<<endl;getchar();getchar();return 0;}四、实验总结通过这次实验基本弄清了停止等待协议的工作机理。
网络协议原理实验报告
![网络协议原理实验报告](https://img.taocdn.com/s3/m/9a860953fd4ffe4733687e21af45b307e971f96b.png)
网络协议原理实验报告1. 实验目的本实验旨在通过实际操作,理解和掌握网络协议的基本原理,包括数据传输过程中的分段、封装和解封装等关键步骤,以及网络协议的工作方式和作用。
2. 实验环境- 操作系统:Windows 10- 软件工具:Wireshark、Tera Term3. 实验内容3.1 数据传输过程的分段和封装首先,我们需要进行数据传输过程的分段和封装操作。
为了简化实验,我们选取一个简单的应用场景:从计算机A向计算机B发送一段文字信息。
步骤如下:1. 打开Tera Term,分别在计算机A和计算机B上运行。
2. 在计算机A上输入文字信息,例如:“Hello World!”。
3. 在计算机A上使用Wireshark进行抓包操作,监听计算机A与计算机B之间的数据传输过程。
4. 在计算机A上点击发送按钮,将文字信息发送给计算机B。
3.2 网络协议的工作方式和作用在数据传输过程中,网络协议起到了关键的作用。
具体来说,网络协议分为多个层次,每个层次都有自己的功能和任务。
其中,最为常见的是TCP/IP协议。
步骤如下:1. 在Wireshark抓包工具中,我们可以看到整个数据传输过程中的分段、封装以及网络协议的工作方式。
2. 在Wireshark中,我们可以看到每个数据包的详细信息,包括源IP地址、目的IP地址、数据长度等。
3. 在Wireshark中,我们还可以追踪每个数据包的传输路径,以及每个路由器的IP地址和工作状态。
4. 实验结果与分析根据实验步骤,我们可以得出如下实验结果与分析:- 在计算机A上输入文字信息并发送后,Wireshark抓包工具会显示对应的发送数据包。
- 在Wireshark中,我们可以看到每个数据包的详细信息,包括源IP地址、目的IP地址、数据长度等。
- 在Wireshark中,我们还可以追踪每个数据包的传输路径,以及每个路由器的IP地址和工作状态。
通过实验结果与分析,我们可以得出以下结论:- 在数据传输过程中,数据被分成多个较小的分段,分别进行封装。
传输协议gbn
![传输协议gbn](https://img.taocdn.com/s3/m/cf1c89bed4d8d15abe234e59.png)
竭诚为您提供优质文档/双击可除传输协议gbn篇一:计算机网络原理实验五传输层可靠传输协议gbn 编程实验报告云南大学软件学院实验报告实验五、传输层可靠传输协议gbn编程实验报告一、实验目的:1、编程实现简单可靠的数据传输gbn协议,模拟可靠数据传输2、理解tcp协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
二、实验指导:参考教材。
三、实验要求:编程实现一个gbn传输协议,采用编程语言不限,要求能将发送――接收流程以及处理方法表现出来.附源代码及四、实验总结1.通过看代码了解了编程实现简单可靠的数据传输gbn 协议,模拟可靠数据传输2.要理解tcp协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
3.packet是pkt结构体类型.调用此函数将此分组发送到网络中,前往另一个实体。
篇二:计网实验五-传输层可靠传输协议gbn编程实验报告实验五、传输层可靠传输协议gbn编程实验报告序号:姓名:学号:成绩一、实验目的:1、编程实现简单可靠的数据传输gbn协议,模拟可靠数据传输2、理解tcp协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
二、实验指导:参考教材。
三、实验要求:编程实现一个gbn传输协议,采用编程语言不限,要求能将发送――接收流程以及处理方法表现出来.附源代码及程序流程图如下:实验截图如下:四、实验总结通过本次实验,了解了gbn传输协议的相关知识。
实验代码通过查阅资料很容易理解,但是怎么实现这个程序对我来说是个问题。
后来我把程序分了3部分,一个头文件和两个源文件,通过visualstudio可以良好的运行。
篇三:gbn和sR的优劣比较gbn和sR的优劣比较摘要:gbn和sR协议是tcp协议中重要的两种解决流水线的差错恢复的方法,他们各自有各自的优缺点,在不同的数据传输条件下,人们将会有不同的选择。
让大家了解两种方法的优劣本文做了简单的叙述。
关键字:gbn(go-back-n)sR(selectiverepeat)gbn概念:gbn是go-back-n协议的缩写。
网络协议实验报告讲解
![网络协议实验报告讲解](https://img.taocdn.com/s3/m/eee29860cdbff121dd36a32d7375a417866fc1d8.png)
网络协议实验报告讲解引言在计算机网络中,网络协议是指计算机网络中各个实体进行通信、交换数据时所遵循的规则和约定。
网络协议的设计和实现对于网络的性能和稳定性有着重要的影响。
为了更好地理解和掌握网络协议的工作原理和应用,本次实验我们进行了网络协议的实验,并在此基础上撰写了本篇实验报告,旨在通过讲解实验内容和结果,对网络协议的相关知识进行深入的学习和探讨。
实验目的本次实验的主要目的是通过实际操作,对网络协议进行深入研究和探讨。
具体实验目标如下:1. 理解网络协议的基本概念和主要作用;2. 学习使用网络协议进行数据通信和交换;3. 掌握网络协议的实验操作和设计。
实验环境本次实验环境如下:1. 操作系统:Windows 10;2. 软件工具:Wireshark、Ping、Traceroute等。
实验过程本次实验分为三个部分,分别是TCP/IP协议、DNS协议和HTTP 协议。
下面将对每个部分进行详细讲解。
1. TCP/IP协议TCP/IP协议是互联网中最重要的一种网络协议,它采用分层结构,包括了物理层、数据链路层、网络层和传输层。
在本次实验中,我们主要关注传输层的TCP协议和UDP协议。
(略去部分内容)2. DNS协议DNS(Domain Name System)协议是互联网中的一种应用层协议,它的主要作用是将域名解析为IP地址,实现域名和IP地址之间的转换。
本次实验我们使用Wireshark工具进行DNS报文的捕获和分析。
(略去部分内容)3. HTTP协议HTTP(HyperText Transfer Protocol)协议是一种用于传输超文本的应用层协议,它是Web应用中最重要的一种协议。
在本次实验中,我们使用Wireshark工具对HTTP请求和响应进行捕获和分析。
(略去部分内容)实验结果与分析在实验过程中,我们捕获了大量的网络数据包,并使用Wireshark 工具进行了分析。
通过对各个协议的数据包进行解析和比较,我们得出了以下几点实验结果和分析:1. TCP与UDP的区别从实验结果来看,TCP协议和UDP协议在传输方式、可靠性和效率等方面存在明显的差异。
计算机网络实验-传输层协议分析
![计算机网络实验-传输层协议分析](https://img.taocdn.com/s3/m/6b0f2c02ba1aa8114431d9ed.png)
实验四、传输层协议分析【实验目的】1. 通过捕获TCP 包并进行分析,了解传输层协议的工作过程,加深对TCP 及面向连接的服务的工作原理的理解与掌握,2. 观察简单的TCP 流传输,理解其首部各字段的变化。
3. 理解UDP 数据报的传输特点。
【实验原理】【实验内容】1、查看分析TCP 链路管理(1)、在PC2(192.168.2.24)中安装有FTP 服务端程序。
(2)、在PC1 中开启协议分析软件,进行数据包抓包。
(3)、在PC1 中的协议分析软件中利用工具栏中的TCP 连接工具对PC2 发起连接,如下图所示。
PC1 主动打开连接请求确认PC2 被动打开确认确认SYN ,SEQ = xACK,SEQ = x+1,ACK = y +1SYN,ACK,SEQ = y , ACK = x+1图 4-12 TCP连接工具在IP地址中填入PC2地址192.168.2.24,端口填入FTP服务端口21,然后点击连接。
分析捕获到的三次握手报文。
图 4-13 三次握手第一次连接查看上图TCP报文中的报头部分:源端口:3241,由于发起连接的是客户端,因此源端口为TCP程序随机出的短暂端口,在此连接中是3241。
目的端口:21,由于是向FTP服务发起连接,因此目的端口为FTP服务的熟知端口,为21。
序列号:0X732020CD,此序列号为TCP程序随机出的字节编号。
确认序号:0X00000000,第一个发出的连接请求中,确认号为0。
TCP首部长度:7,TCP首部长度包括TCP报头长度和数据长度,这个字段表示TCP报头长度,其中20字节为标准TCP报头长度,另有8字节选项字段长度,选项字段中和服务器端协商了最大报文段长度。
标识位:SYN位置1,只有TCP连接中三次握手第一次连接的报文段中SYN位置1。
窗口大小:65535,默认大小。
校验和:0X5D64,校验和是对TCP报头、数据和伪首部进行计算得出的校验和。
编程实现可靠数据传输原理GO-BAN-N实验报告
![编程实现可靠数据传输原理GO-BAN-N实验报告](https://img.taocdn.com/s3/m/b0ffc11603d8ce2f0066238f.png)
编程实现可靠数据传输原理GO-BACK-N实验姓名:吴杰学号:13281144 班级:计科1306一.实验目的运用各种变成语言实现基于Go-Back-N的可靠数据传输软件二.实验意义通过本实验,使学生能够对可靠数据传输原理有进一步的理解和掌握。
三.实验步骤1.利用java编程实现基于Go-Back-N的可靠数据传输软件。
2.运行程序,程序将模拟实际网络中的可靠数据传输四.结果分析通过本次实验,了解了GBN传输协议的相关知识。
实验代码通过查阅资料很容易理解,但是怎么实现这个程序对我来说是个问题。
五.附件JAVA语言代码(1)Sender类package GBN;import java.util.Timer;public class Sender extends Thread{public int windowsize=3; //发送方窗口长度设为3public String[] data={"data1","data2","data3","data4","data5","data6","data7"}; //模拟七个数据包public int sign[]={0,1,2,3,4,5,6}; //为7个数据包标号public int localack=-1; //保存最近收到的ACKpublic Timers litime=null; //定时器(这里定为2秒)public int switches=0; //超时标志,1为超时public int windowsign[]; //当前窗口内待发的数据分组的序号public int acksign=0; //为0表示收到正确ACK,为1表示收到错误的ACK,必须重发!public Sender(){windowsign=new int[windowsize]; //给窗口分配指定大小的空间for(int i=0;i<3;i++)windowsign[i]=sign[i]; //窗口初始化时存放前3个序号}public void run(){System.out.println("发送方开始发送分组数据!");}public void getack(int ack){System.out.println("发送方收到了ACK,序号为"+ack+"并且开始加以确认!");if(ack!=localack+1){System.out.println("经验证,这不是发送方正期待的ACK,立刻重发序号为"+(localack+1)+"的数据分组!");acksign=1;}else{localack=ack; //表示正确确认了ACKacksign=0;}}public void time(){switches=0; //标志初始化为0litime=new Timers();Timer limit=new Timer();limit.schedule(litime, 0,100);}}(2)Receiver类package GBN;public class Receiver extends Thread{public int lastdata;public Sender sender;public void run(Sender s){sender=s;System.out.println("接收方开始接收分组数据!");}void receive(int data, Sender s){sender=s; //发送方的参数传递System.out.println("接收方收到了序号为"+data+"的分组!");if(data!=0){if(data==lastdata+1){ //数据包序号校验,若连续则是正确/所期待的System.out.println("该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!");lastdata=data; //更新本地保存的数据包序号变量respond(lastdata); //回送该正确接收的数据包对应的ACK }else{System.out.println("该数据分组不是接收方所期待的,该分组将被丢弃,接收方准备回送最后接受的数据分组对应的ACK!");respond(lastdata);//若不是所期待的数据包则丢弃并且重发上一次的ACK}}else{System.out.println("该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!");lastdata=data;respond(lastdata); //首次接收数据包并且回送ACK }}void respond(int ack){ //回送指定序号的ACK if(sender.litime.limit<20){ //判断是否超时(2秒)ack=lastdata; //获取本场保存的数据包序号sender.getack(ack);}else{System.out.println("计时超时!!(未丢包但是时间超过2秒)发送方准备重发序号为"+ack+"的数据分组!");sender.switches=1; //如果超时,设置超时状态并显示警告}}}(3)Timers类package GBN;import java.util.TimerTask;public class Timers extends TimerTask {public int switches;public int limit;public void run(){if(limit<20) limit++; //计时2秒else {switches=-1;this.cancel();} //开关为-1表示超时,并且停止计时器}public Timers(){switches=0; //启动计时器时全部初始化limit=0;}}(4)GBN类package GBN;import java.util.Random;import java.io.*;public class GBN extends Thread{static void senddelay(int x) throws InterruptedException{if(x==1) {sleep(300);System.out.println("发送数据分组时发生延迟:300毫秒!");}else if(x==2) {sleep(750);System.out.println("发送数据分组时发生延迟:750毫秒!");}else if(x==3) {sleep(1200);System.out.println("发送数据分组时发生延迟:1200毫秒!");}else if(x==4) {sleep(3000);System.out.println("发送数据分组时发生延迟:3000毫秒!");}}public static void main(String[] args) throws IOException, InterruptedException { Sender s=new Sender();Receiver re=new Receiver();s.start();//发送端启动re.run(s);//接收端启动sleep(1000);//延迟处理int[] retimes=new int[7]; //计算每个分组被发送的次数for(int i=0;i<7;i++)retimes[i]=0;//数据包顺次发送for(int i=0;i<=s.sign.length;i++){while(i>s.localack+1){//尚有未确认的数据包,重发!System.out.println("发送方开始重新发送序号为"+(s.localack+1)+"的数据分组");retimes[s.localack+1]++;int ran=new Random().nextInt(3);int randelay=new Random().nextInt(5);s.time();senddelay(randelay);//设置随机值,模拟数据传输延迟if(ran!=1)re.receive(s.localack+1,s);//设置随机值,模拟数据丢包过程elseSystem.out.println("序号为"+(s.localack+1)+"的分组在传给接收方途中发生了丢包!");}if(i!=s.sign.length){System.out.println();System.out.println("发送方现在开始第一次发送序号为"+i+"的数据分组");retimes[i]++;if(i!=0){for(int k=0;k<3;k++){//表示至少成功发送并确认了一个数据分组s.windowsign[k]++;//这种情况下滑动窗口向前移动!}}System.out.println();System.out.println("当前窗口内的分组情况为:");//显示当前窗口内数据包情况for(int p=0;p<3;p++){if(s.windowsign[p]<=6)System.out.println("第"+p+"号窗口里面存放的是序号为"+s.windowsign[p]+"的马上待发送的数据分组!");elseSystem.out.println("第"+p+"号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!");}System.out.println();int ran=new Random().nextInt(3);int randelay=new Random().nextInt(5);s.time();//计时开始(2秒时间)senddelay(randelay);//设置随机值,模拟数据传输延迟if(ran!=1) re.receive(s.sign[i],s);//设置随机值,模拟数据丢包过程else System.out.println("序号为"+i+"的分组在传给接收方途中发生了丢包!");}}System.out.println();System.out.println("以下是每个数据分组被发送过的次数的统计结果");for(int i=0;i<7;i++)//显示关于每个数据包发送次数的统计表System.out.println("序号为"+i+"的数据分组被发送过的次数为:"+retimes[i]);System.exit(0);}}。
网络协议实验报告
![网络协议实验报告](https://img.taocdn.com/s3/m/c0c8e7c9a1116c175f0e7cd184254b35eefd1a07.png)
网络协议实验报告摘要:本实验报告旨在研究和分析网络协议的重要性以及如何使用它们来实现安全和高效的数据传输。
通过实验,我们深入了解了几种常见的网络协议,并通过实际操作了解了它们的工作原理和应用场景。
实验结果表明,在合适的环境下,网络协议能够确保数据的可靠传输,并提供一定程度的安全性保障。
1. 引言网络协议是计算机网络中实现数据传输的基础。
它们定义了数据如何在计算机网络中传递和交换,确保数据的可靠性、安全性和高效性。
在本次实验中,我们将重点研究以下几种网络协议:1.1. TCP/IP协议TCP/IP协议是互联网中最常用的网络协议之一。
它分为四层:网络接口层、网络层、传输层和应用层。
每一层都有特定的功能和任务。
网络协议的实现和使用牵涉到各个层次的相关技术和配置。
1.2. HTTP协议HTTP协议是用于在Web浏览器和Web服务器之间传输超文本的协议。
它基于TCP/IP协议,并通过可靠的连接进行数据传输。
通过HTTP协议,我们可以实现网页的请求和响应,以及其他与Web相关的操作。
HTTP协议的实现和使用在今天的互联网中至关重要。
2. 实验目的本次实验的目的是:2.1. 理解和掌握各种网络协议的工作原理和应用场景;2.2. 通过实际操作验证网络协议的功能和效果;2.3. 探索网络协议在实际应用中的安全性和可靠性。
3. 实验过程3.1. 搭建实验环境在实验开始前,我们需要搭建一个适合的实验环境。
确保计算机网络的正常连接,并安装必要的软件和工具。
3.2. 实验一:TCP/IP协议实验在第一个实验中,我们将研究TCP/IP协议的工作原理,并进行一系列的实际操作。
首先,我们需要了解和配置网络接口层的相关参数。
接下来,我们将实现网络层和传输层的功能,包括IP地址的分配和路由的配置。
最后,我们将使用应用层协议进行数据传输,并验证其可靠性和效果。
3.3. 实验二:HTTP协议实验在第二个实验中,我们将以HTTP协议为例,研究应用层协议的工作流程和功能。
2023年计算机网络实验报告(6篇)
![2023年计算机网络实验报告(6篇)](https://img.taocdn.com/s3/m/565423e5a48da0116c175f0e7cd184254b351beb.png)
计算机网络实验报告(6篇)计算机网络实验报告(通用6篇)计算机网络实验报告篇1一、实验目的1、熟悉微机的各个部件;2、掌握将各个部件组装成一台主机的方法和步骤;3、掌握每个部件的安装方法;4、了解微型计算机系统的基本配置;5、熟悉并掌握DOS操作系统的使用;6、掌握文件、目录、路径等概念;7、掌握常用虚拟机软件的安装和使用;8、熟悉并掌握虚拟机上WINDOWS操作系统的安装方法及使用;9、掌握使用启动U盘的制作和U盘安装windows操作系统的方法;10、了解WINDOWS操作系统的基本配置和优化方法。
二、实验内容1.将微机的各个部件组装成一台主机;2.调试机器,使其正常工作;3.了解计算机系统的基本配置。
4.安装及使用虚拟机软件;5.安装WINDOWS7操作系统;6.常用DOS命令的使用;7.学会制作启动U盘和使用方法;8.WINDOWS7的基本操作;9.操作系统的基本设置和优化。
三、实验步骤(参照实验指导书上的内容,结合实验过程中做的具体内容,完成此项内容的撰写)四、思考与总结(写实验的心得体会等)计算机网络实验报告篇2windows平台逻辑层数据恢复一、实验目的:通过运用软件R-Studio_5.0和winhe_对误格式化的硬盘或者其他设备进行数据恢复,通过实验了解windows平台逻辑层误格式化数据恢复原理,能够深入理解并掌握数据恢复软件的使用方法,并能熟练运用这些软件对存储设备设备进行数据恢复。
二、实验要求:运用软件R-Studio_5.0和winhe_对电脑磁盘或者自己的U盘中的删除的数据文件进行恢复,对各种文件进行多次尝试,音频文件、系统文件、文档文件等,对简单删除和格式化的磁盘文件分别恢复,并检查和验证恢复结果,分析两个软件的数据恢复功能差异与优势,进一步熟悉存储介质数据修复和恢复方法及过程,提高自身的对存储介质逻辑层恢复技能。
三、实验环境和设备:(1)Windows _P 或Windows 20__ Professional操作系统。
传输层协议分析实验报告
![传输层协议分析实验报告](https://img.taocdn.com/s3/m/a5a178281fb91a37f111f18583d049649a660e76.png)
传输层协议分析实验报告一、实验目的本实验旨在通过对传输层协议的深入分析和研究,掌握传输层协议的工作原理和实现机制,并以此为基础,进一步理解网络通信的整体结构和工作流程。
二、实验原理传输层协议是计算机网络中负责端到端通信的协议,常用的传输层协议有TCP和UDP。
TCP(Transmission Control Protocol)提供可靠的、面向连接的通信服务,保证数据的完整性和顺序。
UDP(User Datagram Protocol)则提供无连接的通信服务,数据传输速度快但不保证数据的可靠性。
三、实验内容本实验主要分为两部分,第一部分是对TCP协议的分析,第二部分是对UDP协议的分析。
1.TCP协议分析首先,我们通过抓包工具Wireshark,捕获一段TCP协议的通信数据。
然后,我们观察捕获到的数据包,分析TCP的连接建立、数据传输和连接释放的过程。
在连接建立阶段,我们可以看到TCP连接的三次握手过程,即客户端向服务器发送SYN报文段,服务器回复SYN+ACK报文段,客户端再次回复ACK报文段。
通过这个过程,建立了客户端和服务器之间的可靠连接。
在数据传输阶段,我们可以看到TCP协议通过序号和确认号来保证数据的可靠性。
发送方将数据划分为若干个报文段,并为每个报文段分配一个序号。
接收方在接收到报文段后,通过确认号告知发送方已接收到数据,并通过序号保证数据的顺序。
在连接释放阶段,我们可以看到TCP连接的四次挥手过程,即发送方向接收方发送FIN报文段,接收方回复ACK报文段,然后接收方再向发送方发送FIN报文段,发送方回复ACK报文段。
通过这个过程,断开了客户端和服务器之间的连接。
根据抓包分析的结果,我们对TCP协议的工作原理有了更深入的理解。
2.UDP协议分析接下来,我们捕获一段UDP协议的通信数据,并通过Wireshark进行分析。
与TCP不同,UDP是一种无连接的协议,数据传输快速但不保证数据的可靠性。
计算机网络与通信传输层协议分析实验报告
![计算机网络与通信传输层协议分析实验报告](https://img.taocdn.com/s3/m/82ffb075cf84b9d529ea7a20.png)
南昌航空大学实验报告年月日课程名称:计算机网络与通信实验名称:传输层协议分析班级:学生姓名:学号: 2212893107指导教师评定:签名:一.实验目的理解TCP报文首部格式和字段的作用,TCP连接的建立和释放过程,TCP数据传输的编号与确认的过程;学习TFTP工具3CDaemon软件的使用,分析UDP协议报文格式。
二.实验内容1.TCP协议基本分析2. UDP协议分析三.实验过程1.TCP协议基本分析1.TCP的报文格式,2. TCP连接的建立,3. TCP数据的传送4. TCP连接的释放步骤1 相邻两台机器分别为PCA和PCB。
在PCB上下载并安装Telnetd,然后建立用于登录的用户和密码。
步骤2在PCA上运行WireShark进行报文截获,同时设置相应的显示过滤规则。
步骤3PCA上打开Windows命令窗口,执行telnet到PCB,然后执行“exit”退出,从而完成一次TCP协议连接的建立和释放。
步骤4分析截获报文中数据发送部分的第一条TCP报文及其确认报文。
步骤5步骤6TCP连接建立时,其报文首部与其他TCP报文不同,有一个option字段,它的作用是什么,值给多少?结合IEEE802.3协议规定的以太网最大帧长度分析此数据是怎么样得出的。
步骤7分析TCP连接的释放过程中,选择TCP连续撤消的四个报文,将报文信息填入下表:步骤8分析TCP数据传送阶段的前8个报文,将报文信息填入下表:请写出TCP 数据部分长度的计算公式。
数据传送阶段第一个报文的序号字段值是否等于连接建立时第三个报文的序号? 2. UDP 协议分析步骤1相邻两台机器分别为PCA 和PCB 。
步骤2 根据3CDeamon 软件的配置,在PCA 上配置TFTP server 功能,在PCB 上配置TFTP client 功能。
选择TFTP client 要从TFTP server 下载的文件名。
步骤3 运行PCA 、PCB 上的Wireshark ,开始报文截获。
传输层协议分析实验报告(五篇模版)
![传输层协议分析实验报告(五篇模版)](https://img.taocdn.com/s3/m/e6a22c0782c4bb4cf7ec4afe04a1b0717fd5b310.png)
传输层协议分析实验报告(五篇模版)第一篇:传输层协议分析实验报告2.传输层协议分析2.A 数据包捕获分析部分2.1 实验目的理解TCP 报文首部格式和字段的作用,TCP 连接的建立和释放过程,TCP 数据传输中编号与确认的作用。
2.2 实验内容应用 TCP 应用程序传输文件,截取 TCP 报文,分析TCP 报文首部信息,TCP 连接的建立过程,TCP 数据的编号和确认机制。
2.3 实验原理TCP 协议是传输控制协议的简称,工作在网络层协议之上,是面向连接的,可靠的,端到端的传输层协议。
1)TCP 的报文格式 TCP 报文段分为头部和数据两部分,如图 1:图 1TCP 报文段的总体结构 TCP 首部 TCP 数据部分TCP 报文段首部又分为固定部分和选项部分,固定部分为20B,如图 2 所示,这些字段的组合实现了 TCP 的所有功能。
图 2 TCP 报文段的首部源端口目的端口序号确认号头部长度(4bit)保留 U R G A C K P S H R S T S Y N F I N窗口校验和紧急指针选项(长度可变)填充 TCP 采用传输输连接的方式传送 TCP 报文,传输连接包括连接建立、数据传输和连接释放三个阶段。
2)TCP 连接的建立 TCP 连接建立采用“3 次握手”方式。
首先,主机 A 的 TCP 向主机 B 的 TCP 发出连接请求报文段,其首部中的同步位 SYN 应置 1,同时选择一个序号 X,表明在后面传送数据时的第一个数据字节的序号是 X+1,如图 3所示:图 3TCP 连接建立的 3 次握手过程然后,主机 B 的 TCP 收到连接请求报文段后,若同意,则发回确认。
在确认报文段中应将 SYN 和 ACK 都置 1,确认号应为 X+1,同时也为自己选择一个序号 Y。
最后,主机 A 的 TCP 收到 B 的确认后,要向 B 发回确认,其 ACK 置 1,确认号为 Y+1,而自己的序号为 X+1。
传输层实验报告心得
![传输层实验报告心得](https://img.taocdn.com/s3/m/23ad956a66ec102de2bd960590c69ec3d4bbdb00.png)
一、实验背景随着计算机网络技术的飞速发展,传输层协议在计算机网络通信中扮演着至关重要的角色。
为了更好地理解传输层协议的工作原理,提高自己的网络通信能力,我们进行了传输层实验。
通过本次实验,我对传输层协议有了更加深入的认识,以下是我对本次实验的心得体会。
二、实验目的1. 理解传输层协议的基本概念和功能;2. 掌握TCP和UDP协议的工作原理;3. 分析TCP和UDP协议在实际应用中的优缺点;4. 提高网络通信能力,为今后的网络编程打下基础。
三、实验内容1. TCP协议分析(1)实验步骤①编写TCP客户端程序,向服务器发送数据;② 编写TCP服务器程序,接收客户端发送的数据;③ 分析TCP报文首部信息,了解TCP连接的建立、数据传输和连接释放过程。
(2)实验心得通过本次实验,我深入了解了TCP协议的工作原理。
TCP协议采用面向连接的方式,在传输数据前需要建立连接,传输完成后释放连接。
在实验过程中,我掌握了TCP三次握手、四次挥手的过程,以及TCP报文首部中各个字段的作用。
2. UDP协议分析(1)实验步骤① 编写UDP客户端程序,向服务器发送数据;② 编写UDP服务器程序,接收客户端发送的数据;③ 分析UDP报文首部信息,了解UDP协议的特点。
(2)实验心得UDP协议与TCP协议相比,具有传输速度快、无连接、不可靠等特点。
通过本次实验,我掌握了UDP协议的工作原理,了解了UDP报文首部信息,以及UDP在实际应用中的优缺点。
四、实验总结1. 理解了传输层协议的基本概念和功能,掌握了TCP和UDP协议的工作原理;2. 分析了TCP和UDP协议在实际应用中的优缺点,为今后的网络编程打下了基础;3. 提高了网络通信能力,为解决实际网络问题积累了经验。
五、展望通过本次实验,我对传输层协议有了更加深入的认识。
在今后的学习和工作中,我将继续关注网络通信技术的发展,努力提高自己的网络编程能力。
同时,我将不断拓展自己的知识面,为我国计算机网络事业贡献自己的力量。
gbn协议
![gbn协议](https://img.taocdn.com/s3/m/d127d04c91c69ec3d5bbfd0a79563c1ec5dad7b2.png)
GBN协议简介GBN(Go-Back-N)协议是一种流量控制协议,用于在计算机网络中可靠地传输数据。
它是一种数据链路层协议,确保数据在发送方和接收方之间的可靠传输。
工作原理GBN协议通过在发送方和接收方之间维护一个滑动窗口来实现可靠传输。
滑动窗口的大小表示发送方未确认的数据包数目。
发送方按照窗口的大小将数据包发送给接收方。
接收方在正确收到数据包后发送确认消息,发送方收到确认消息后将滑动窗口向前滑动,继续发送下一个数据包。
如果发送方在一定时间内没有收到确认消息,它将重新发送滑动窗口中的所有数据包。
这样确保了数据的可靠传输。
GBN协议的特点1.流量控制:GBN协议通过滑动窗口的大小控制数据包的发送速率,以避免发送方发送过多数据导致接收方缓冲区溢出。
2.可靠性:GBN协议通过确认消息和超时重传机制确保数据的可靠传输。
发送方会不断重传未收到确认消息的数据包,直到接收方正确接收。
3.有序性:GBN协议保证接收方按照发送方发送的顺序接收数据包,不会发生乱序。
GBN协议的优缺点优点•实现相对简单:GBN协议的实现相对简单,适用于网络环境较为良好的情况。
•可靠性较高:通过确认消息和超时重传机制,GBN协议能够确保数据的可靠传输。
缺点•延迟较高:GBN协议的延迟较高,因为发送方需要等待确认消息才能发送下一个数据包。
•信道利用率低:当发生数据包丢失或损坏时,发送方需要重传整个滑动窗口中的数据包,导致信道利用率降低。
使用GBN协议的应用场景GBN协议适用于对数据可靠性要求较高的场景,例如: - 文件传输:在文件传输过程中,确保文件的完整性是非常重要的。
GBN协议可以用于在不可靠的网络环境中可靠地传输文件。
- 视频流传输:对于实时性较强的视频流传输,GBN协议可以确保视频数据的有序接收,减少视频播放的卡顿和断续。
总结GBN协议是一种可靠的流量控制协议,通过滑动窗口和确认消息机制实现数据的可靠传输。
虽然有一定的延迟和信道利用率低的缺点,但在对数据可靠性要求较高的场景下,GBN协议仍然是一种有效的选择。
传输层实训报告
![传输层实训报告](https://img.taocdn.com/s3/m/f7b1362530b765ce0508763231126edb6f1a76ac.png)
一、实训目的本次传输层实训旨在使学生深入了解传输层协议的工作原理,掌握传输层协议的基本概念、功能以及实现方法。
通过实训,提高学生对传输层协议的理解和实际应用能力,为后续网络编程和系统设计打下坚实基础。
二、实训环境1. 操作系统:Windows 102. 编程语言:Python3.83. 库:socket库4. 实验工具:PyCharm IDE三、实训原理传输层负责在网络中提供端到端的通信服务,其主要协议有TCP和UDP。
TCP(传输控制协议)是一种面向连接的、可靠的传输层协议,它通过三次握手建立连接,并在数据传输过程中保证数据的完整性和顺序。
UDP(用户数据报协议)是一种无连接的、不可靠的传输层协议,它不保证数据传输的完整性和顺序,但具有较低的延迟和较小的开销。
四、实训过程1. TCP协议实现(1)创建TCP服务器端程序,使用socket库的socket()函数创建一个socket 对象,并绑定到指定的端口。
(2)使用listen()函数使socket对象处于监听状态,等待客户端连接。
(3)使用accept()函数接受客户端连接,创建新的socket对象用于与客户端通信。
(4)使用recv()和send()函数进行数据传输。
(5)关闭socket对象,结束通信。
(6)编写TCP客户端程序,使用与服务器端类似的步骤实现数据传输。
2. UDP协议实现(1)创建UDP服务器端程序,使用socket库的socket()函数创建一个socket 对象,并绑定到指定的端口。
(2)使用recvfrom()函数接收客户端发送的数据,并获取客户端的IP地址和端口号。
(3)使用sendto()函数向客户端发送数据。
(4)关闭socket对象,结束通信。
(5)编写UDP客户端程序,使用与服务器端类似的步骤实现数据传输。
五、实训结果1. 成功实现了TCP和UDP协议的基本功能,包括连接建立、数据传输和连接关闭。
2. 通过实际编程,加深了对传输层协议的理解,掌握了TCP和UDP协议的实现方法。
计算机网络原理实验七、传输层可靠传输协议GBN编程实验报告
![计算机网络原理实验七、传输层可靠传输协议GBN编程实验报告](https://img.taocdn.com/s3/m/2b9e58715727a5e9846a6125.png)
实验七、传输层可靠传输协议GBN编程实验报告序号:姓名:学号:成绩指导老师:一、实验目的:1、通过编写实现一个简单可靠的数据传输协议GBN的发送和接收代码,模拟可靠数据传输2、理解TCP协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
二、实验原理:在GBN中,发送端不需要在接收到上一个数据包的ACK后才发送下一个数据包,而是可以连续发送数据包。
在发送端发送数据包的过程中,如果接收到对应已发送的某个数据包的NACK,则发送端将NACK对应的某个数据包进行重发,然后再将该数据包之后的数据包依次进行重发。
三、结果分析:本次试验中采用java语言进行程序编写代码注释:(一)S ender类import java.util.Timer;public class Sender extends Thread{public int windowsize=3; //发送方窗口长度设为3public String[] data={"data1","data2","data3","data4","data5","data6","data7"}; //模拟七个数据包public int sign[]={0,1,2,3,4,5,6}; //为7个数据包标号public int localack=-1; //保存最近收到的ACKpublic Timers litime=null; //定时器(这里定为2秒)public int switches=0; //超时标志,1为超时public int windowsign[]; //当前窗口内待发的数据分组的序号public int acksign=0;//为0表示收到正确ACK,为1表示收到错误的ACK,必须重发!public Sender(){windowsign=new int[windowsize];//给窗口分配指定大小的空间for(int i=0;i<3;i++)windowsign[i]=sign[i]; //窗口初始化时存放前3个序号}public void run(){System.out.println("发送方开始发送分组数据!");}public void getack(int ack){System.out.println("发送方收到了ACK,序号为"+ack+"并且开始加以确认!");if(ack!=localack+1){System.out.println("经验证,这不是发送方正期待的ACK,立刻重发序号为"+(localack+1)+"的数据分组!");acksign=1;}else{localack=ack; //表示正确确认了ACKacksign=0;}}public void time(){switches=0; //标志初始化为0litime=new Timers();Timer limit=new Timer();limit.schedule(litime, 0,100);}}(二)R eceiver类import java.util.Random;public class Receiver extends Thread{public int lastdata;public Sender sender;public void run(Sender s){sender=s;System.out.println("接收方开始接收分组数据!");}void receive(int data, Sender s){sender=s; //发送方的参数传递System.out.println("接收方收到了序号为"+data+"的分组!");if(data!=0){if(data==lastdata+1){//数据包序号校验,若连续则是正确/所期待的System.out.println("该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!");lastdata=data; //更新本地保存的数据包序号变量respond(lastdata); //回送该正确接收的数据包对应的ACK }else{System.out.println("该数据分组不是接收方所期待的,该分组将被丢弃,接收方准备回送最后接受的数据分组对应的ACK!");respond(lastdata);//若不是所期待的数据包则丢弃并且重发上一次的ACK }}else{System.out.println("该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!");lastdata=data;respond(lastdata); //首次接收数据包并且回送ACK }}void respond(int ack){ //回送指定序号的ACK if(sender.litime.limit<20){ //判断是否超时(2秒)ack=lastdata; //获取本场保存的数据包序号sender.getack(ack);}else{System.out.println("计时超时!!(未丢包但是时间超过2秒)发送方准备重发序号为"+ack+"的数据分组!");sender.switches=1; //如果超时,设置超时状态并显示警告}}}(三)T imers类import java.util.TimerTask;public class Timers extends TimerTask {public int switches;public int limit;public void run(){if(limit<20) limit++; //计时2秒else {switches=-1;this.cancel();} //开关为-1表示超时,并且停止计时器}public Timers(){switches=0; //启动计时器时全部初始化limit=0;}}(四)G BN类import .*;import java.util.Random;import java.io.*;public class GBN extends Thread{static void senddelay(int x) throws InterruptedException{if(x==1) {sleep(300); System.out.println("发送数据分组时发生延迟:300毫秒!"); }else if(x==2) {sleep(750); System.out.println("发送数据分组时发生延迟:750毫秒!");}else if(x==3) {sleep(1200);System.out.println("发送数据分组时发生延迟:1200毫秒!");}else if(x==4) {sleep(3000);System.out.println("发送数据分组时发生延迟:3000毫秒!");}else;}public static void main(String[] args) throws IOException,InterruptedException {Sender s=new Sender();Receiver re=new Receiver();s.start(); //发送端启动re.run(s); //接收端启动sleep(1000); //延迟处理int[] retimes=new int[7];//计算每个分组被发送的次数for(int i=0;i<7;i++) retimes[i]=0; //数据包顺次发送for(int i=0;i<=s.sign.length;i++){while(i>s.localack+1){ //尚有未确认的数据包,重发!System.out.println("发送方开始重新发送序号为"+(s.localack+1)+"的数据分组");retimes[s.localack+1]++;int ran=new Random().nextInt(3);int randelay=new Random().nextInt(5);s.time();senddelay(randelay); //设置随机值,模拟数据传输延迟if(ran!=1) re.receive(s.localack+1,s);//设置随机值,模拟数据丢包过程else System.out.println("序号为"+(s.localack+1)+"的分组在传给接收方途中发生了丢包!");}if(i!=s.sign.length){System.out.println();System.out.println("发送方现在开始第一次发送序号为"+i+"的数据分组");retimes[i]++;if(i!=0){for(int k=0;k<3;k++){//表示至少成功发送并确认了一个数据分组s.windowsign[k]++;//这种情况下滑动窗口向前移动!}}System.out.println();System.out.println("当前窗口内的分组情况为:");//显示当前窗口内数据包情况for(int p=0;p<3;p++){if(s.windowsign[p]<=6)System.out.println("第"+p+"号窗口里面存放的是序号为"+s.windowsign[p]+"的马上待发送的数据分组!");elseSystem.out.println("第"+p+"号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!");}System.out.println();int ran=new Random().nextInt(3);int randelay=new Random().nextInt(5);s.time(); //计时开始(2秒时间)senddelay(randelay); //设置随机值,模拟数据传输延迟if(ran!=1) re.receive(s.sign[i],s);//设置随机值,模拟数据丢包过程else System.out.println("序号为"+i+"的分组在传给接收方途中发生了丢包!");}}System.out.println();System.out.println("以下是每个数据分组被发送过的次数的统计结果");for(int i=0;i<7;i++) //显示关于每个数据包发送次数的统计表System.out.println("序号为"+i+"的数据分组被发送过的次数为:"+retimes[i]);System.exit(0);}}结果截图:。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验七、传输层可靠传输协议GBN编程实验报告序号:姓名:学号:成绩指导老师:一、实验目的:1、通过编写实现一个简单可靠的数据传输协议GBN的发送和接收代码,模拟可靠数据传输2、理解TCP协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
二、实验原理:在GBN中,发送端不需要在接收到上一个数据包的ACK后才发送下一个数据包,而是可以连续发送数据包。
在发送端发送数据包的过程中,如果接收到对应已发送的某个数据包的NACK,则发送端将NACK对应的某个数据包进行重发,然后再将该数据包之后的数据包依次进行重发。
三、结果分析:本次试验中采用java语言进行程序编写代码注释:(一)S ender类import java.util.Timer;public class Sender extends Thread{public int windowsize=3; //发送方窗口长度设为3public String[] data={"data1","data2","data3","data4","data5","data6","data7"}; //模拟七个数据包public int sign[]={0,1,2,3,4,5,6}; //为7个数据包标号public int localack=-1; //保存最近收到的ACKpublic Timers litime=null; //定时器(这里定为2秒)public int switches=0; //超时标志,1为超时public int windowsign[]; //当前窗口内待发的数据分组的序号public int acksign=0;//为0表示收到正确ACK,为1表示收到错误的ACK,必须重发!public Sender(){windowsign=new int[windowsize];//给窗口分配指定大小的空间for(int i=0;i<3;i++)windowsign[i]=sign[i]; //窗口初始化时存放前3个序号}public void run(){System.out.println("发送方开始发送分组数据!");}public void getack(int ack){System.out.println("发送方收到了ACK,序号为"+ack+"并且开始加以确认!");if(ack!=localack+1){System.out.println("经验证,这不是发送方正期待的ACK,立刻重发序号为"+(localack+1)+"的数据分组!");acksign=1;}else{localack=ack; //表示正确确认了ACKacksign=0;}}public void time(){switches=0; //标志初始化为0litime=new Timers();Timer limit=new Timer();limit.schedule(litime, 0,100);}}(二)R eceiver类import java.util.Random;public class Receiver extends Thread{public int lastdata;public Sender sender;public void run(Sender s){sender=s;System.out.println("接收方开始接收分组数据!");}void receive(int data, Sender s){sender=s; //发送方的参数传递System.out.println("接收方收到了序号为"+data+"的分组!");if(data!=0){if(data==lastdata+1){//数据包序号校验,若连续则是正确/所期待的System.out.println("该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!");lastdata=data; //更新本地保存的数据包序号变量respond(lastdata); //回送该正确接收的数据包对应的ACK }else{System.out.println("该数据分组不是接收方所期待的,该分组将被丢弃,接收方准备回送最后接受的数据分组对应的ACK!");respond(lastdata);//若不是所期待的数据包则丢弃并且重发上一次的ACK }}else{System.out.println("该数据分组正是接收方所期待的,接收方接受了它并准备回送对应的ACK!");lastdata=data;respond(lastdata); //首次接收数据包并且回送ACK }}void respond(int ack){ //回送指定序号的ACK if(sender.litime.limit<20){ //判断是否超时(2秒)ack=lastdata; //获取本场保存的数据包序号sender.getack(ack);}else{System.out.println("计时超时!!(未丢包但是时间超过2秒)发送方准备重发序号为"+ack+"的数据分组!");sender.switches=1; //如果超时,设置超时状态并显示警告}}}(三)T imers类import java.util.TimerTask;public class Timers extends TimerTask {public int switches;public int limit;public void run(){if(limit<20) limit++; //计时2秒else {switches=-1;this.cancel();} //开关为-1表示超时,并且停止计时器}public Timers(){switches=0; //启动计时器时全部初始化limit=0;}}(四)G BN类import .*;import java.util.Random;import java.io.*;public class GBN extends Thread{static void senddelay(int x) throws InterruptedException{if(x==1) {sleep(300); System.out.println("发送数据分组时发生延迟:300毫秒!"); }else if(x==2) {sleep(750); System.out.println("发送数据分组时发生延迟:750毫秒!");}else if(x==3) {sleep(1200);System.out.println("发送数据分组时发生延迟:1200毫秒!");}else if(x==4) {sleep(3000);System.out.println("发送数据分组时发生延迟:3000毫秒!");}else;}public static void main(String[] args) throws IOException,InterruptedException {Sender s=new Sender();Receiver re=new Receiver();s.start(); //发送端启动re.run(s); //接收端启动sleep(1000); //延迟处理int[] retimes=new int[7];//计算每个分组被发送的次数for(int i=0;i<7;i++) retimes[i]=0; //数据包顺次发送for(int i=0;i<=s.sign.length;i++){while(i>s.localack+1){ //尚有未确认的数据包,重发!System.out.println("发送方开始重新发送序号为"+(s.localack+1)+"的数据分组");retimes[s.localack+1]++;int ran=new Random().nextInt(3);int randelay=new Random().nextInt(5);s.time();senddelay(randelay); //设置随机值,模拟数据传输延迟if(ran!=1) re.receive(s.localack+1,s);//设置随机值,模拟数据丢包过程else System.out.println("序号为"+(s.localack+1)+"的分组在传给接收方途中发生了丢包!");}if(i!=s.sign.length){System.out.println();System.out.println("发送方现在开始第一次发送序号为"+i+"的数据分组");retimes[i]++;if(i!=0){for(int k=0;k<3;k++){//表示至少成功发送并确认了一个数据分组s.windowsign[k]++;//这种情况下滑动窗口向前移动!}}System.out.println();System.out.println("当前窗口内的分组情况为:");//显示当前窗口内数据包情况for(int p=0;p<3;p++){if(s.windowsign[p]<=6)System.out.println("第"+p+"号窗口里面存放的是序号为"+s.windowsign[p]+"的马上待发送的数据分组!");elseSystem.out.println("第"+p+"号窗口已经空了,并且后续窗口、发送方没有要发送的数据分组了!");}System.out.println();int ran=new Random().nextInt(3);int randelay=new Random().nextInt(5);s.time(); //计时开始(2秒时间)senddelay(randelay); //设置随机值,模拟数据传输延迟if(ran!=1) re.receive(s.sign[i],s);//设置随机值,模拟数据丢包过程else System.out.println("序号为"+i+"的分组在传给接收方途中发生了丢包!");}}System.out.println();System.out.println("以下是每个数据分组被发送过的次数的统计结果");for(int i=0;i<7;i++) //显示关于每个数据包发送次数的统计表System.out.println("序号为"+i+"的数据分组被发送过的次数为:"+retimes[i]);System.exit(0);}}结果截图:。