续上次 计算机网络实验 Go Back N (不含 ACK)滑动窗口协议 C++

今天实现了 带有 ACK 的

环境 :Microsoft Visual C++ 6.0

代码实现:

#include <iostream>
#include <cstring>
#include "protocol.h"
#include "datalink.h"
using namespace std  ;
#pragma comment ( lib  , "Protocol.lib" )
#define rep ( i , j , n ) for ( int i = int(j) ; i < int(n) ; ++i )
// 帧类型
#define FRAME_DATA 1
#define FRAME_ACK  2
// 窗口大小定义
#define MAX_SEQ 7
// 超时规定
#define DATA_TIMER  1200
#define ACK_TIMER 300
// 帧数据结构定义namespace YHL {class FRAME { public:unsigned char type ;            // 种类unsigned char ack ;             // ackunsigned char seq ;             // 序号unsigned char data[PKT_LEN] ;   // 数据部分unsigned int  padding ; public:FRAME () {}FRAME ( unsigned char _type , unsigned char _seq , unsigned char _ack ): type ( _type ), ack ( _ack ) , seq ( _seq ){}} One ;    // One 作为反复使用的帧// 事件参数int arg = 0 ;   // 物理层是否准备好了              int phl_ready = 0 ; // 发送方的左边界    unsigned char ack_expected = 0 ;// 发送方的右边界 + 1unsigned char next_frame_to_send = 0 ;// 接受窗口正在移动的号unsigned char frame_expected = 0 ;// 发送窗口的数量unsigned char nbuffered = 0 ;// 存储发送窗口unsigned char out_buf[MAX_SEQ+1][PKT_LEN] ;// 令窗口滑动, 不超过 MAX_SEQunsigned char Go_On ( unsigned char &NO ) {return NO = ( NO + 1 ) % ( MAX_SEQ + 1 ) ;}        // 判断 ack 是否落在发送窗口内int between ( unsigned char a , unsigned char b , unsigned char c ) {return ( ( ( a <= b ) && ( b < c ) ) || ( ( c < a ) && ( a <= b ) ) || ( ( b < c ) && ( c < a ) ) ) ;}// 添加 CRC 校验, 发往物理层void Add_Crc_and_Send ( unsigned char *frame , int len ) { *(unsigned int *)( frame + len ) = crc32 ( frame , len ) ;send_frame ( frame , len + 4 ) ;phl_ready = 0 ;}// 发送一个数据帧void Send_Data_Frame ( unsigned char type , unsigned char frame_nr , unsigned char frame_expected ) {int ack = ( frame_expected + MAX_SEQ ) % ( MAX_SEQ + 1 ) ;FRAME One ( type , frame_nr , ack ) ;switch ( type ) {case FRAME_DATA : {memcpy ( One.data , out_buf[frame_nr] , PKT_LEN ) ;dbg_frame ( "Send DATA %d %d , ID %d\n" , One.seq , One.ack , *(short *)One.data ) ;Add_Crc_and_Send ( (unsigned char *)&One , 3 + PKT_LEN ) ; start_timer ( frame_nr , DATA_TIMER ) ;    break ;}case FRAME_ACK : {dbg_frame("Send ACK  %d\n" , One.ack ) ;Add_Crc_and_Send ( (unsigned char *)&One , 3 ) ;break ;}}    stop_ack_timer () ; // 现在我已经发出去了, 所以先暂停 ack          }// 网络层准备好了void Net_Layer_OK ()  {++nbuffered ;                get_packet ( out_buf[next_frame_to_send] ) ;Send_Data_Frame ( FRAME_DATA , next_frame_to_send , frame_expected ) ;Go_On ( next_frame_to_send ) ;}// 收到一个数据帧void Recieve_Data () {// 先进行校验int len = recv_frame ( (unsigned char *)&One , sizeof One ) ;if ( len < 5 || crc32 ( (unsigned char *)&One , len ) ) {dbg_frame ( "Recv Bad packet\n" ) ;return ;}switch ( One.type ) {// 收到的是数据帧case FRAME_DATA : {if ( One.seq == frame_expected ) {dbg_frame ( "Recv DATA %d %d , ID %d\n" , One.seq , One.ack , *(short *)One.data ) ; put_packet ( One.data , len - 7 ) ; // 减去七位非数据位Go_On ( frame_expected ) ;start_ack_timer ( ACK_TIMER ) ;}break ;}// 收到的是 ACK 帧case FRAME_ACK : {dbg_event ( "Recv ACK  %d\n" , One.ack ) ; break ;}default : break ;}// 看是否可以腾出发送窗口的左边while ( between ( ack_expected , One.ack , next_frame_to_send ) ) {--nbuffered ;stop_timer ( ack_expected ) ;Go_On ( ack_expected ) ;}}// 协议初始化void Init_Protocol ( int argc , char **argv ) {protocol_init ( argc , argv ) ;lprintf ( "Fluence_YHL : " __DATE__"  "__TIME__"\n" ) ;disable_network_layer () ;}// 如果 ack 超时了void Data_Time_Out () {dbg_event ( "---- DATA %d timeout\n" , arg ) ;  // 要传的下一帧是 ack_expected, 也就是左边界    // Go Back N 就体现在这里   next_frame_to_send = ack_expected ;for ( int i = 1 ; i <= nbuffered ; ++i ) {Send_Data_Frame ( FRAME_DATA , next_frame_to_send , frame_expected ) ;Go_On ( next_frame_to_send ) ;}}void ACK_Time_Out () {dbg_event ( "ACK  %d  time is out " , arg ) ;Send_Data_Frame ( FRAME_ACK , next_frame_to_send , frame_expected ) ;}// 控制网络层开闭void Enable_Net_Layer () {if ( nbuffered < MAX_SEQ && phl_ready )enable_network_layer() ;elsedisable_network_layer() ;}// 获取一个事件int Get_event () {return wait_for_event ( &arg ) ;}
}int main ( int argc , char **argv ) {YHL::Init_Protocol ( argc , argv ) ;while ( true ) {// 获取一个事件int event = YHL::Get_event () ;switch ( event ) {// 网络层准备好了case NETWORK_LAYER_READY : YHL::Net_Layer_OK () ; break ;// 收到一个帧case FRAME_RECEIVED : YHL::Recieve_Data () ; break ;// 物理层准备好了case PHYSICAL_LAYER_READY : YHL::phl_ready = 1 ; break ;// 超时重发case DATA_TIMEOUT : YHL::Data_Time_Out () ; break ;// case ACK_TIMEOUT : YHL::ACK_Time_Out () ; break ;default : break ;}// 控制网络层流量YHL::Enable_Net_Layer () ;}return 0 ;
}

程序结果:

计算机网络实验 Go Back N (带有ACK)滑动窗口协议 C++相关推荐

  1. 计算机网络笔记(5) 传输层滑动窗口协议(GBN、SR)

    文章目录 滑动窗口协议(Sliding-window protocol) GBN(Go-Back-N/后退N帧协议) SR协议(Selective Repeat/选择重传协议) 滑动窗口协议(Slid ...

  2. c语言退回N帧滑动窗口协议,滑动窗口协议实验的报告.docx

    滑动窗口协议实验的报告 滑动窗口协议实验报告 篇一:Exp1_滑动窗口协议_实验报告 Exp1 滑动窗口协议实验报告 [实验目标] ? 理解和掌握"滑动窗口"技术. ? 基于计算机 ...

  3. 计算机网络 TCP 滑动窗口协议 详解

    滑动窗口机制解析: 1.窗口机制 滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口:同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口.发送窗 ...

  4. 计算机网络实验5以太网链路帧实验,计算机网络实验-使用Wireshark分析以太网帧与ARP协议.docx...

    编号:_______________ 本资料为word版本,可以直接编辑和打印,感谢您的下载 计算机网络实验-使用Wireshark分析以太网帧与ARP协议 计算机网络实验-使用Wireshark分析 ...

  5. 【计算机网络】数据链路层 : 流量控制 ( “流量控制“ 机制 | 停止-等待协议 | 滑动窗口协议 | 后退 N 帧协议 GBN | 选择重传协议 SR | 滑动窗口 与 流量控制、可靠传输 )

    文章目录 一. 数据链路层 流量控制 二. 数据链路层 与 传输层 流量控制 机制 三. 数据链路层 流量控制 四. 数据链路层 流量控制 方法分类 五.停止等待协议 六.滑动窗口协议 七.滑动窗口协 ...

  6. 计算机网络之传输层:6、TCP流量控制、滑动窗口协议

    传输层:6.TCP流量控制 实现流量控制的方法: TCP流量控制: 实现流量控制的方法: 停止等待协议和滑动窗口协议 TCP流量控制:

  7. TCP连续ARQ协议和滑动窗口协议

    TCP协议通过使用连续ARQ协议和滑动窗口协议,来保证数据传输的正确性,从而提供可靠的传输. 一.ARQ协议 ARQ协议,即自动重传请求(Automatic Repeat-reQuest),是OSI模 ...

  8. 三句话介绍清楚滑动窗口协议/GBN/SR

    滑动窗口协议.GBN.SR之间不得不说的故事 首先我们来介绍什么是滑动窗口协议 滑动窗口协议(Sliding Window Protocol),属于TCP协议的一种应用,用于网络数据传输时的流量控制, ...

  9. TCP 滑动窗口协议 详解

    滑动窗口机制 (1).窗口机制     滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口:同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口. ...

最新文章

  1. java记事本环境变量_java环境变量配置以及用记事本写程序
  2. 别在 Java 代码里乱打日志了,这才是正确的打日志姿势!
  3. (转)创业需要知道的13句话
  4. php 获得当月时间戳,php获取当前月与上个月月初及月末时间戳的方法
  5. 商场专柜私收银现象治理要点
  6. codeforces332B - Maximum Absurdity 线段数 or dp
  7. 数据库事物 jdbc事物 spring事物 隔离级别:脏幻不可重复读
  8. 点云质量评估_Chamfer Distance--倒角距离
  9. 单片机通过改变占空比改变电机转速c语言,直流电动机的调速 用单片机产生PWM控制...
  10. web前端开发前景如何
  11. 多个app用同一个签名文件_运动设备和运动APP的合理搭配
  12. 抢红包案例分析以及代码实现(二)
  13. 怎么把备忘录中的视频导到手机相册里
  14. 金山 V8 终端安全系统 默认弱口令漏洞
  15. Gif动图如何在线编辑?教你三步在线编辑动图
  16. 基本概念:转发和重定向
  17. 【白话机器学习】算法理论+实战之决策树
  18. iOS内购-iap-In-App Purchases-开发及注意事项
  19. Mac终端添加快捷命令
  20. 5G网络(手机Wifi)快速入门

热门文章

  1. 金融信创虽风正时济,应对挑战该如何乘风破浪(一)
  2. 键盘输入,键盘输入结束符。
  3. 茜在人名可以读xi吗_茜读xi还是qian?
  4. 使用Adobe Acrobat XI Pro进行pdf裁剪
  5. docker提交比赛记录
  6. Joel 技术分享心得
  7. 并发与并行,线程与进程如何理解
  8. 数据结构电梯模拟 100梯1000层 不限梯数
  9. html把保留图片改为提交按钮,如何制作图片按钮,并为图片按钮添加提交表单和重置表单功能...
  10. 设计模式 - 漫谈软件编程背后的系统化思维