数据链路层选择重传协议不同于停等协议和go-backn,选择重传协议是接收方窗口是固定大小为(MAX_SEQ+1)/2
发送方窗口是0--(MAX_SEQ+1)/2,采用捎带确认,而且加入NAK,分别有两个计时器,ACK定时器和数据定时器
话不多说 上代码!!!!
#include <stdio.h>
#include <string.h>
#include "protocol.h"
#include "datalink.h"
#define DATA_TIMER 3000 //数据计时器
#define ACK_TIMER 1000 //ACK计时器
#define MAX_SEQ 31
#define NR_BUFS ((MAX_SEQ+1)/2)
typedef enum { false, true }boolean;//布尔变量
struct FRAME {
unsigned char kind; // FRAME_DATA ,FRAME_NAK ,FRAME_ACK
unsigned char ack;
unsigned char seq;
unsigned char data[PKT_LEN];
unsigned int padding;
};
boolean arrive[NR_BUFS];//标记接收缓冲区是否被占用
int no_nak = 1;//没有nak发送
static unsigned char nbuffered = 0;//当前发送缓存数目
static unsigned char in_buffer[NR_BUFS][PKT_LEN], out_buffer[NR_BUFS][PKT_LEN];//接收,发送缓存
static int phl_ready = 0;//表示物理层没就绪
static unsigned char ack_expected = 0, next_frame_to_send = 0;//发送窗口下界和上界
static unsigned char frame_expected = 0, too_far = NR_BUFS;//接收窗口下界和上界
static int between(unsigned char a, unsigned char b, unsigned char c)
{
return (((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a)));
}
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(unsigned char F_kind, unsigned char frame_nr)//发送包的函数,可能是DATA 或ACK 或NAK
{
struct FRAME s;
s.kind = F_kind;
s.seq = frame_nr;
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1);
switch (F_kind)
{
case FRAME_DATA:
{
for (int i = 0; i < PKT_LEN; i++)
s.data[i] = out_buffer[frame_nr%NR_BUFS][i];
dbg_frame("Send DATA %d %d, ID %d\n", s.seq, s.ack, *(short *)s.data);
put_frame((unsigned char *)&s, 3 + PKT_LEN);//CRC已经加完 并且已经向物理层发送一帧
start_timer(frame_nr % NR

本文介绍了一种使用C语言编写的数据链路层选择重传协议。该协议中,发送方和接收方窗口大小固定,采用捎带确认和NAK机制,并包含两个计时器。代码中详细展示了协议的实现,包括发送数据帧、确认帧和NAK帧的逻辑。此外,还提供了主函数和关键函数`send_data_frame()`的实现。
最低0.47元/天 解锁文章
247





