Go Back N C语言实现(无ACK)

jasonkent27 · · 1881 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。


#include <stdio.h>
#include <string.h>

#include "protocol.h"
#include "datalink.h"
#define MAX_SEQ 6
#define DATA_TIMER  2600

#define inc(k) if(k<MAX_SEQ) k=k + 1;else k = 0

typedef struct								//定义数据包packet 
{
	unsigned char data[PKT_LEN];
}	packet;   

typedef enum 
{
	true,false
} boolean ;

typedef unsigned int seq_nr ;

typedef struct								//定义帧frame
{ 
    unsigned char kind;						// FRAME_DATA 
    unsigned char ack;
    unsigned char seq;
    unsigned char data[PKT_LEN]; 
    unsigned int  padding;
} frame ;

static int phylsical_ready = 0;						//物理层是否准备好的标志,为1表示物理层已准备好,为0表示物理层没准备好.
seq_nr next_frame_to_send=0;
seq_nr ack_expected=0;
seq_nr frame_expected=0;
seq_nr nbuffered = 0;				//正在用的缓存
frame  f;
seq_nr i;		
packet buffer[MAX_SEQ+1];			
int event,arg,len;					//事件,帧长度

static boolean between(seq_nr a, seq_nr b, seq_nr 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);
    phylsical_ready = 0;
}

static void send_data(seq_nr frame_nr,seq_nr frame_expected,packet buffer[])
{
	frame f;

	f.kind = FRAME_DATA;										//帧的类型
	f.seq = frame_nr;										//给帧加序号
	f.ack = ( frame_expected + MAX_SEQ ) % ( MAX_SEQ + 1 ) ;					//捎带确认
	memcpy(f.data, buffer[frame_nr].data, PKT_LEN);							//将buffer[frame_nr]中的数据拷贝到s.data中
	
	dbg_frame("Send DATA %d %d, ID %d\n", f.seq, f.ack, *(short *)f.data);
	put_frame( (unsigned char *)&f, 3 + PKT_LEN );									 //传输帧
	start_timer(frame_nr, DATA_TIMER);									   	//启动计时器   
}


int main(int argc,char **argv)
{

	protocol_init(argc, argv);
	lprintf("Designed by nancyyihao, build: " __DATE__"  "__TIME__"\n");
	disable_network_layer();

	while(1)	
	{
		
		event = wait_for_event(&arg);

		switch(event)
		{
			case NETWORK_LAYER_READY:
					get_packet( buffer[next_frame_to_send].data );					//收到一个新的packet 
					//lprintf("Send DATA %d\n",sizeof(buffer[next_frame_to_send].data)/ sizeof(buffer[next_frame_to_send].data[0]) );
					nbuffered = nbuffered + 1 ;	
					send_data(next_frame_to_send, frame_expected,&buffer);
					inc(next_frame_to_send);						//发送者窗口前移(上限前移)
				break;

			case PHYSICAL_LAYER_READY:
				phylsical_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;
						 }
					 if (f.kind == FRAME_DATA)
							{
								dbg_frame("Recv DATA %d %d, ID %d\n", f.seq, f.ack, *(short *)f.data);
								//lprintf("Recv DATA %d\n",sizeof(f.data) / sizeof(f.data[0]));
								if(f.seq == frame_expected)				//收到了期待的帧
									{			
										put_packet(f.data, len-7);		//上交数据给网络层
										inc(frame_expected);			//接收方窗口前移(下限前移)
									}
							}
							while(between(ack_expected, f.ack, next_frame_to_send))			//处理捎带确认
							{
									nbuffered = nbuffered - 1 ;
									stop_timer(ack_expected);				//收到帧,计时器停止
									inc(ack_expected);					//缩小发送者窗口
							}					
				break;

			case DATA_TIMEOUT:
				dbg_event("---- DATA %d timeout\n", arg) ; 
				next_frame_to_send = ack_expected ;								//开始重传
					for( i=1 ; i <= nbuffered ; i++ )
					{
						send_data(next_frame_to_send, frame_expected,&buffer);			//重传
						inc(next_frame_to_send);						//准备下一个要传的dd帧
					}
				break;
		}

		if( ( nbuffered < MAX_SEQ ) && phylsical_ready  )
			enable_network_layer();
		else
			disable_network_layer();
	}
}



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

本文来自:CSDN博客

感谢作者:jasonkent27

查看原文:Go Back N C语言实现(无ACK)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1881 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传