go back n协议c语言,Go Back N C语言(有ACK)

#include

#include

#include "protocol.h"

#include "datalink.h"

#define DATA_TIMER 3000

#define ACK_TIMER 1500

#define MAX_SEQ 7

void inc(unsigned char* number)

{

(*number)++;

if(*number==MAX_SEQ+1)

*number=0;

}

struct FRAME {

unsigned char kind; /* FRAME_DATA */

unsigned char ack;

unsigned char seq;

unsigned char data[PKT_LEN];

unsigned int padding;

};

struct ACK_FRAME {

unsigned char kind; /* FRAME_DATA */

unsigned char ack;

unsigned int padding;

};

static unsigned char frame_nr = 0;//next frame to send

static unsigned char ack_expected = 0;

static unsigned char buffer[MAX_SEQ+1][PKT_LEN];//

static unsigned char nbuffered = 0;//缓冲区大小

static unsigned char frame_expected = 0;

static int phl_ready = 0;

static void put_frame(unsigned char *frame, int len)

{

*(unsigned int *)(frame + len) = crc32(frame, len);

send_frame(frame, len + 4);

phl_ready = 0;

}

static void send_data_frame(void)

{

struct FRAME s;

s.kind = FRAME_DATA;

s.seq = frame_nr;

s.ack = (frame_expected+MAX_SEQ)%(MAX_SEQ+1);// 另一端的ack

memcpy(s.data, buffer[frame_nr], PKT_LEN);

dbg_frame("Send DATA %d %d, ID %d\n", s.seq, s.ack, *(short *)s.data);

put_frame((unsigned char *)&s, 3 + PKT_LEN);

start_timer(frame_nr, DATA_TIMER);

stop_ack_timer();

}

static void send_ack_frame(void)

{

struct ACK_FRAME s;

s.kind = FRAME_ACK;

s.ack = (frame_expected+MAX_SEQ)%(MAX_SEQ+1);

dbg_frame("Send ACK %d\n", s.ack);

put_frame((unsigned char *)&s, 2);

stop_ack_timer();

}

int BetweenAN(unsigned char a , unsigned char b , unsigned char c)

{

if(((a<=b)&&(b

{

return 1;

}

else

{

return 0;

}

}

int main(int argc, char **argv)

{

int event, arg;

struct FRAME f;

int len = 0;

unsigned char i;

protocol_init(argc, argv);

lprintf("Designed by Jiang Yanjun, build: " __DATE__" "__TIME__"\n");

lprintf("The argc is: %d , the argv is: %s\n",argc,*argv);

disable_network_layer();

for (;;) {

event = wait_for_event(&arg);

switch (event) {

case NETWORK_LAYER_READY:

get_packet(buffer[frame_nr]); //取得数据

nbuffered++;

send_data_frame();

inc(&frame_nr);// next frame to send ++

break;

case PHYSICAL_LAYER_READY:

phl_ready = 1;

break;

case FRAME_RECEIVED:

len = recv_frame((unsigned char *)&f, sizeof f);

if (len < 5 || crc32((unsigned char *)&f, len) != 0)

{

dbg_event("**** Receiver Error, Bad CRC Checksum\n");

break;

}

else

{

if (f.kind == FRAME_ACK)

dbg_frame("Recv ACK %d\n", f.ack);

if (f.kind == FRAME_DATA)

{

dbg_frame("Recv DATA %d %d, ID %d\n", f.seq, f.ack, *(short *)f.data);

if (f.seq == frame_expected)

{

dbg_frame("Recv DATA %d %d, ID %d\n put it to the NetWork\n", f.seq, f.ack, *(short *)f.data);

put_packet(f.data, len - 7);

inc(&frame_expected); // frame expected ++

start_ack_timer(ACK_TIMER);

}

else

dbg_frame("Recv DATA %d %d, ID %d\n but it won't be put\n", f.seq, f.ack, *(short *)f.data);

}

while(BetweenAN(ack_expected,f.ack,frame_nr))

{

nbuffered--;

stop_timer(ack_expected);

inc(&ack_expected);

}

// send_ack_frame();

}

/* if (f.ack == frame_nr)

{

stop_timer(frame_nr);

nbuffered--;

frame_nr = 1 - frame_nr;

}*/

break;

case DATA_TIMEOUT:

dbg_event("---- DATA %d timeout\n", arg);

frame_nr=ack_expected; //全部重发

for(i=1;i<=nbuffered;i++)

{

send_data_frame();

inc(&frame_nr);

}

break;

case ACK_TIMEOUT:

dbg_event("---- ACK %d timeout\n", arg);

send_ack_frame();

break;

}

if (nbuffered < MAX_SEQ && phl_ready)

enable_network_layer();

else

disable_network_layer();

}

}

有疑问加站长微信联系(非本文作者)

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模仿数据链路层的gobackn协议 /*该协议是搭载ack的回退n步协议*/ #include #include "protocol.h" #define max_seq 7 #define flag 126 #define ESC 100 #define wait_time 2700 //发送计时器等待的时间 #define ack_wait_time 280 static int phl_ready = 0; unsigned char buf[max_seq+1][270]; unsigned char ack[8]; //发送空的ack帧 unsigned char in_buf[600], last_buf[520];//接收时的缓冲区;去掉冗余之后的缓冲区,为防备因误码两帧合并为一帧而定义了很大一个数组 int nbuffered=0; //发送的帧数 int buf_size[max_seq+1]; //记下以发送各帧的帧长 int next_frame_to_send=0; int frame_in_phl=0; //用于成帧 int frame_expected=0; int ack_expected=0; int between(int a,int b,int c) { if( ((a<=b)&&(b<c)) || ((c<a)&&(a<=b)) || ((b<c)&&(c<a)) ) return 1; else return 0; } //判断帧尾,防止出现误判esc esc flag为数据的情况 int end_flag(int in_len) { int count=0; int i; if(in_len=0;i--)//记录flag前的esc数目 count++; return count%2; //若flag前的esc为偶数,则为帧尾 }//成帧函数--数据帧 void send_frame(char *my_buf,int len) { int n; buf[frame_in_phl][0]=(frame_expected+max_seq)%(max_seq+1); //ack buf[frame_in_phl][1]=frame_in_phl; //发送帧的帧号 for(n=0;n<len;n++) buf[frame_in_phl][n+2]=my_buf[n]; //将处理过的新帧赋值到缓冲区中 len=len+2; *(unsigned int *)(buf[frame_in_phl]+len) = crc32(buf[frame_in_phl],len); //在原始帧的基础上加检验和 buf_size[frame_in_phl]=len+4; //记录当前帧的长度,包括3个帧头,4个检验和 nbuffered=nbuffered+1; //缓冲区占用数加一 frame_in_phl=(frame_in_phl+1)%(max_seq+1); } //成帧函数--ack帧 void send_ack() //ack帧的处理 { ack[0]=(frame_expected+max_seq)%(max_seq+1); ack[1]=max_seq+10; //ack帧的序号位,使ack[1]==frame_expected恒不成立 *(unsigned int *)(ack+2) = crc32(ack,2); //在原始帧的基础上加检验和 } //主函数 int main(int argc, char **argv) { int event, arg, n , m , i , j , len = 0 ,in_len = 0; unsigned char my_buf[260]; int phl_wait=0; //在物理层中还没有被发送的帧 protocol_init(argc, argv); enable_network_layer(); for (;;) { event = wait_for_event(&arg); switch (event) { case NETWORK_LAYER_READY:
好的,以下是一个简单的 C++ 程序,用于模拟实现 Go-back-N 协议: ```c++ #include <iostream> #include <vector> using namespace std; // 数据包结构体 struct Packet { int seq; // 序号 string data; // 数据 }; // 发送方发送数据 void sender(vector<Packet>& packets, int window_size, int timeout) { int next_seq = 0; // 下一个要发送的序号 int base = 0; // 窗口起始位置 int unacked = 0; // 已发送但未确认的数据包数量 // 模拟循环发送数据包 while (true) { // 发送窗口内的未确认数据包 while (unacked < window_size && next_seq < packets.size()) { cout << "发送数据包 " << next_seq << endl; // 模拟发送数据包 // send_packet(packets[next_seq]); next_seq++; unacked++; } // 等待确认或超时 // receive_ack(timeout); // 检查是否有确认 if (unacked > 0) { cout << "等待确认..." << endl; // 模拟接收确认 bool received_ack = true; if (received_ack) { cout << "接收到确认 " << base << endl; base++; unacked--; } else { cout << "未接收到确认,超时重传" << endl; next_seq = base; unacked = 0; } } // 检查是否已发送完毕 if (base == packets.size()) { break; } } } // 接收方接收数据 void receiver(vector<Packet>& packets, int window_size, int timeout) { int expected_seq = 0; // 期望接收的序号 int base = 0; // 窗口起始位置 // 模拟循环接收数据包 while (true) { // 模拟接收数据包 Packet packet; // 接收到的数据包 // receive_packet(packet); // 如果接收到的数据包的序号等于期望接收的序号 if (packet.seq == expected_seq) { cout << "接收到数据包 " << expected_seq << ",并发送确认" << endl; // 模拟发送确认 // send_ack(expected_seq); expected_seq++; base++; // 将窗口向前滑动,以便接收更多数据包 while (packets[base].seq < expected_seq && base < packets.size()) { base++; } } else { cout << "接收到数据包 " << packet.seq << ",但不是期望接收的序号" << endl; // 模拟发送确认 // send_ack(expected_seq - 1); } // 检查是否已接收完毕 if (base == packets.size()) { break; } } } int main() { // 创建数据包 vector<Packet> packets; packets.push_back({0, "Hello"}); packets.push_back({1, "World"}); packets.push_back({2, "Go-back-N"}); packets.push_back({3, "Protocol"}); packets.push_back({4, "Simulation"}); packets.push_back({5, "Example"}); // 设置窗口大小和超时时间 int window_size = 3; int timeout = 500; // 启动发送方和接收方 sender(packets, window_size, timeout); receiver(packets, window_size, timeout); return 0; } ``` 上述程序实现了一个简单的 Go-back-N 协议模拟。在程序中,发送方和接收方都使用了一个循环来模拟数据包的发送和接收过程。在发送过程中,发送方会根据窗口大小和超时时间来控制发送的数据包数量,并等待接收到确认或超时后重传。在接收过程中,接收方会等待接收到数据包后发送确认,并将窗口向前滑动以便接收更多的数据包。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值