7滑动窗口协议模拟
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);
实验 8 滑动窗口协议模拟
一、实验目的
1. 模拟实现滑窗协Байду номын сангаас在数据链路层上的数据传输过程, 加深对滑 窗协议的理解 2. 掌握滑动窗口协议基本原理与基本算法;
二、要求:
1.掌握滑动窗口协议的概念、原理与基本算法; 2.实现“选择性重传策略或连续自动重传策略(后退 N 帧) ”的滑 动窗口协议模拟程序; 3.了解传输层和链路层滑动窗口协议的区别与联系及 TCP 中滑动 窗口协议的实现原理。
} 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) {
则超时重发。因此,发送方在每发完一个数据帧时都要设置超时计时器。只要在 所设置的计时器超时而仍未收到确认帧,就要重发相应的数据帧,若等不到 1 号帧的确认应答而重发 1 号数据帧时,虽然发送方已经发送完 3 号帧,但仍必须 将 1 号帧及其以后的各帧全部进行重传。因此,后退 N 帧协议一方面因连续发送 数据帧而提高了效率, 但另一方面,在重传时又必须把原来已正确传送过的数据 帧进行重传,这种做法又使传送率降低。
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]; //接
受 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;