当前位置:文档之家› 7滑动窗口协议模拟

7滑动窗口协议模拟


} return 0; } /* * 选择性重传测试函数 */ int stud_slide_window_choice_frame_resend(char *pBuffer, int bufferSize, UINT8 messageType) { unsigned int ack; unsigned int seq; mainFrame temp; mainFrame send; mainFrame receive; int current_frame; int i; if (messageType == MSG_TYPE_SEND) //发送部分和回退 n 的是一样的 { temp.f = new frame; (*temp.f) = *(frame*)pBuffer; temp.size = bufferSize; choice_send_queue.push_back(temp); if ( current_window_size < WINDOW_SIZE_BACK_N_FRAME) { current_window_size++; send = choice_send_queue.back(); SendFRAMEPacket(((unsigned char*)send.f), send.size); } return 0; } if (messageType == MSG_TYPE_RECEIVE) { frame_kind frame_type = (frame_kind) ntohl(((frame*)pBuffer)->head.kind); //获取帧的类型 ack = ((frame *)pBuffer)->head.ack; if(frame_type==nak) //若是 nak,则重发对应帧 { for (current_frame=0; current_frame < WINDOW_SIZE_BACK_N_FRAME && current_frame < choice_send_queue.size(); current_frame++) { receive = choice_send_queue[current_frame]; if (ack == receive.f->head.seq) {
三、实验原理
滑窗协议工作原理
由于停等协议要为每一个帧进行确认后才继续发送下一个帧, 大大降低了 信道利用率,因此又提出来回退 N 帧的滑窗协议。回退 N 帧协议中,发送方在发 送完一个数据帧后,不停下来等待应答帧,而是连续发送若干个数据帧,即使在 连续发送过程中收到了接收方发来的应答帧,也可以继续发送。由于减少了等待 时间,必然提高通信的吞吐量和信道利用率。 回退 N 帧的滑窗协议(GO-DACK-N)基本原理是,当接收方检测出错的信 息帧后,丢弃出错帧后的所有信息帧,而不管这些帧是否正确。待发送方收到对 出错帧的否定应答(NAK)时,将重发从出错后的所有数据帧;若应答帧出错,
实验 8 滑动窗口协议模拟
一、实验目的
1. 模拟实现滑窗协议在数据链路层上的数据传输过程, 加深对滑 窗协议的理解 2. 掌握滑动窗口协议基本原理与基本算法;
二、要求:
1.掌握滑动窗口协议的概念、原理与基本算法; 2.实现“选择性重传策略或连续自动重传策略(后退 N 帧) ”的滑 动窗口协议模拟程序; 3.了解传输层和链路层滑动窗口协议的区别与联系及 TCP 中滑动 窗口协议的实现原理。
受 ack 及之前的帧 if (ack == receive.f->head.seq) break; } if (current_frame < WINDOW_SIZE_BACK_N_FRAME && current_frame < backn_send_queue.size()) { for (i = 0; i <= current_frame; i++) //关 闭接收完毕的帧对应的窗口 { backn_send_queue.pop_front(); current_window_size--; } } for (i=current_window_size; i < WINDOW_SIZE_BACK_N_FRAME && i < backn_send_queue.size() && current_window_size < WINDOW_SIZE_BACK_N_FRAME; i++) { current_window_size++; //接收完毕 后窗口前移,继续发送 send = backn_send_queue[i]; SendFRAMEPacket(((unsigned char*)send.f), send.size); } return 0; } if (messageType == MSG_TYPE_TIMEOUT) { seq = ntohl(*(unsigned int*)pBuffer); for (current_frame=0; current_frame < WINDOW_SIZE_BACK_N_FRAME && current_frame < backn_send_queue.size(); current_frame++) { send = backn_send_queue[current_frame]; if (seq == send.f->head.seq) //找到重发 的帧在队列中的位置 break; } for (i=current_frame; i < WINDOW_SIZE_BACK_N_FRAME && i < backn_send_queue.size(); i++) { send = backn_send_queue[i]; // 重发其后所有帧 SendFRAMEPacket(((unsigned char*)send.f), send.size); } return 0;
mainFrame receive; if (messageType == MSG_TYPE_SEND) { temp.f = new frame; (*temp.f) = *(frame*)pBuffer; temp.size = bufferSize; stop_wait_send_queue.push_back(temp); //将发送数据封装后压入发 送队列,下同 if ( full == false) //窗口不为空时发送 { full = true; //关闭窗口 send = stop_wait_send_queue.front(); SendFRAMEPacket(((unsigned char*)send.f), send.size); } return 0; } if (messageType == MSG_TYPE_RECEIVE) { ack = ((frame *)pBuffer)->head.ack; if (stop_wait_send_queue.size()!=0) { receive = stop_wait_send_queue.front(); if( ack == (receive.f)->head.seq ) //找到对应 ack 的帧,关闭 该窗口 { stop_wait_send_queue.pop_front(); if (stop_wait_send_queue.size()!=0) { send = stop_wait_send_queue.front(); //等待队列中还有数据的话打开新窗口发送 SendFRAMEPacket(((unsigned char*)send.f), send.size); } } } else { full = false; //接收队列为空则打开新窗 口 } return 0; } if (messageType == MSG_TYPE_TIMEOUT) { seq = ntohl(*(unsigned int*)pBuffer);
四、实验要求
1.Windows XP 环境下运行,程序在 1~2 台 PC 上运行。 2.具体实现的协议可以采用回退 N 帧技术或者选择性重发技术的协议。 3.采用.NET 平台中的 C#、C++或其他编程语言实现。
五、实验内容
模拟滑窗协议的实现过程为; (1) 程序客户端线程发送连接请求。 (2) 服务器连接并返回连接信息。 (3) 客户端发送数据帧(窗口大小自行设定) 。 (4) 服务器对每一个收到数据帧都返回收到信息或者返回数据接收超时信息。 (5) 客户端根据返回信息确定是否重传数据还是选择重传数据。
send = stop_wait_send_queue.front(); //超时重发队列头部的帧 if ( seq == send.f->head.seq ) { SendFRAMEPacket(((unsigned char*)send.f), send.size); } return 0; } return 0; } /* * 回退 n 帧测试函数 */ int stud_slide_window_back_n_frame(char *pBuffer, int bufferSize, UINT8 messageType) { unsigned int ack; unsigned int seq; mainFrame temp; mainFrame send; mainFrame receive; int current_frame; int i; if ( messageType == MSG_TYPE_SEND) { temp.f = new frame; (*temp.f) = *(frame*)pBuffer; temp.size = bufferSize; backn_send_queue.push_back(temp); if ( current_window_size < WINDOW_SIZE_BACK_N_FRAME) //发 送窗口未满时继续发送 { current_window_size++; send = backn_send_queue.back(); SendFRAMEPacket(((unsigned char*)send.f), send.size); } return 0; } if (messageType == MSG_TYPE_RECEIVE) { ack = ((frame *)pBuffer)->head.ack; for (current_frame=0; current_frame < WINDOW_SIZE_BACK_N_FRAME && current_frame < backn_send_queue.size(); current_frame++) { receive = backn_send_queue[current_frame]; //接
则超时重发。因此,发送方在每发完一个数据帧时都要设置超时计时器。只要在 所设置的计时器超时而仍未收到确认帧,就要重发相应的数据帧,若等不到 1 号帧的确认应答而重发 1 号数据帧时,虽然发送方已经发送完 3 号帧,但仍必须 将 1 号帧及其以后的各帧全部进行重传。因此,后退 N 帧协议一方面因连续发送 数据帧而提高了效率, 但另一方面,在重传时又必百度文库把原来已正确传送过的数据 帧进行重传,这种做法又使传送率降低。
【实验过程】 (实验步骤、记录、数据、分析)
客户端的主程序流程图:
数据帧传输服务器端的流程图:
五、详细代码
#include "sysinclude.h" #include <deque> using namespace std; extern void SendFRAMEPacket(unsigned char* pData, unsigned int len); #define WINDOW_SIZE_STOP_WAIT 1 #define WINDOW_SIZE_BACK_N_FRAME 4 typedef enum {data,ack,nak} frame_kind; typedef struct frame_head { frame_kind kind; //帧类型 unsigned int seq; //序列号 unsigned int ack; //确认号 unsigned char data[100]; //数据 }; typedef struct frame { frame_head head; //帧头 unsigned int size; //数据的大小 }; // 需要定义另外一个数据结构来存帧和其大小 typedef struct mainFrame { frame* f; int size; }; deque<mainFrame> stop_wait_send_queue; //停等式协议发送队列 deque<mainFrame> backn_send_queue; //回退 N 式协议发送队列 deque<mainFrame> choice_send_queue; //选择性重传式协议发送队列 bool full = false; //标记停等式时窗口是否为空 int current_window_size = 0; //回退 N 的当前窗口大小 int current_window_size_c = 0; //选择性重传式的当前窗口大小 /* * 停等协议测试函数 */ int stud_slide_window_stop_and_wait(char *pBuffer, int bufferSize, UINT8 messageType) { unsigned int ack; unsigned int seq; mainFrame temp; mainFrame send;
相关主题