按照自己的理解实现比特交换协议(alternating-bit protocol)
一开始的思路是想写两个程序的,发送端和接收端。但是后来想了下,因为是模拟的,所以不用这么麻烦,直接自己定制场景(比如说丢包阿,包出错阿,超时之类的)。
基本上是根据上图所写的,一个函数发包,一个函数接包(比如上图的wait_for_ack0),在这个发包函数里定制场景,在接包函数里处理场景。
说到处理场景,仔细看看wait for ack0上所写的:
翻译一下:
- if ( rdt_rcv(rcvpkt) && (corrupt(rcvpkt)) || isACK(rcvpkt, ) ) // 如果有接受到包且包坏了, 或者接受到的ACK是1,那么就什么都不用做,因为会执行下面的超时函数
- {
- ;// do nothing,静静地等待超时然后重新发包
- }
- if (timeout) // 如果超时,重新发包然后重新启动计时器
- {
- udt_send(sndpkt);
- start_timer;
- }
- if ( rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt, ) ) // 只有凑齐接收到包且包正确且收到的回复正确,那么就可以停止计时了
- {
- stop timer;
- }
因为这是停等协议(stop and wait),所以顺序是先发0包,再发1包,再发0包这样持续下去。
根据场景,我定义了这个一个数组:数据包丢失,确认包丢失,数据包出错,确认包出错,超时 5个场景。 丢失就会超时,出错就是验证校验和。
不过因为我懒,所以没有计算RTT之类的时间,校验和也忽略掉的。
这里给个思路,可以根据公式(大家可以看看计算机网路的书,上面有写算RTT的公式),只要你定义了数据包的大小,网速的话,根据包的个数是可以算出来RTT的。
下面是我自己定义的场景。
- #define PACKAGE_LOSS 0
- #define ACK_LOSS 1
- #define PACK_CORRUPT 2
- #define ACK_CORRUPT 3
- #define TIME_OUT 4
- int Flag[] = {}; // 0代表没有,1代表有
你在调用发包这个函数时就询问会出现哪种场景,我写得代码一次发包只能实现一种场景(不过根据场景的不同,有可能引发其他场景。比如丢包,这样自然就会引起超时了)。
在接收包的函数时,就定义解决场景,根据上图写。
下面给出完整代码(有一些地方可能会出错,但也弄出个大概,仅供参考)
- #include <stdio.h>
- #include <stdlib.h>
- #define DATA_LENGTH 20
- struct Pkt
- {
- int seqnum;
- int checksum;
- char data[DATA_LENGTH];
- };
- #define PACKAGE_LOSS 0
- #define ACK_LOSS 1
- #define PACK_CORRUPT 2
- #define ACK_CORRUPT 3
- #define TIME_OUT 4
- int Flag[] = {};
- int nsimmax = ; // the number of message
- int n_package = ;
- struct Pkt *pkt_ptr = NULL;
- void init()
- {
- int i = ;
- int j = ;
- int k = ;
- printf("---- Stop and Wait Network Simulator Version 1.0 ----\n");
- printf("Enter the number of messages to simulate: ");
- scanf("%d", &nsimmax);
- pkt_ptr = (struct Pkt *)malloc(nsimmax * sizeof(struct Pkt)); // nsimmax packages
- if (pkt_ptr == NULL)
- {
- perror("Malloc Error: ");
- exit();
- }
- // Fill some data in Pkt.data
- for (i = ; i < nsimmax; i++)
- {
- for (j = ; j < DATA_LENGTH; j++)
- {
- pkt_ptr[i].data[j] = + k;
- }
- k++;
- }
- }
- void Question(int *p)
- {
- int i = ;
- printf("--------------\n");
- printf("0 - Nothing wrong\n");
- printf("1 - Packet loss\n");
- printf("2 - ACK loss\n");
- printf("3 - Packet error\n");
- printf("4 - ACK error\n");
- printf("5 - Time out\n");
- printf("--------------\n");
- printf("Choice: ");
- scanf("%d", &i);
- if (i != )
- {
- p[i - ] = ;
- }
- }
- void send()
- {
- if (Flag[] == )
- {
- printf("SEND: Package loss\n");
- Flag[] = ; // time out
- }
- else if (Flag[] == )
- {
- printf("SEND: ACK loss\n");
- Flag[] = ; // time out
- }
- else if (Flag[] == )
- {
- printf("SEND: Packet error\n");
- }
- else if (Flag[] == )
- {
- printf("SEND: ACK error\n");
- }
- else if (Flag[] == )
- {
- printf("SEND: Time out\n");
- }
- else
- {
- printf("SEND: Nothing wrong\n");
- }
- printf("\n");
- }
- void rdt_send0()
- {
- Question(Flag);
- printf("SEND: Send package 0\n");
- printf("SEND: Start timer\n\n");
- send();
- }
- void rdt_send1()
- {
- Question(Flag);
- printf("SEND: Send package 1\n");
- printf("SEND: Start timer\n\n");
- send();
- }
- void waitACK0()
- {
- int i = ;
- while ()
- {
- if ((Flag[] == && Flag[] == ) || Flag[] == )
- {
- printf("-------------------\n");
- if (Flag[] == ) // Send error package
- {
- printf("RECV: SEND NAK0\n");
- }
- if (Flag[] == ) // Error ACK0 means ACK1
- {
- printf("RECV: Receive package 0\n");
- printf("The data is: ");
- for (i = ; i < DATA_LENGTH; i++)
- printf("%c", pkt_ptr[n_package].data[i]);
- printf("\n");
- printf("RECV: SEND ACK1\n");
- printf("SEND: ACK should be 0\n");
- }
- printf("-------------------\n");
- Flag[] = ; // package error or error ACK can lead to time out
- }
- if (Flag[] == ) // time out
- {
- printf("SEND: Time out\n");
- printf("SEND: Resend package0...\n");
- if (Flag[] == ) // package 0 loss
- {
- Flag[] = ;
- }
- if (Flag[] == ) // ACK 0 loss
- {
- printf("RECV: Detetch the redundant, discard the package0\n");
- Flag[] = ;
- }
- if (Flag[] == ) // package 0 error
- {
- Flag[] = ;
- }
- if (Flag[] == )
- {
- printf("RECV: Detetch the redundant, discard the package0\n");
- Flag[] = ;
- }
- printf("SEND: Start timer\n");
- Flag[] = ;
- }
- if (Flag[] == && Flag[] == && Flag[] == )
- {
- printf("SEND: Stop timer\n");
- printf("-------------------\n");
- printf("RECV: reveive package0\n");
- printf("RECV: send ACK0\n");
- printf("The data is: ");
- for (i = ; i < DATA_LENGTH; i++)
- printf("%c", pkt_ptr[n_package].data[i]);
- printf("\n");
- break;
- }
- }
- }
- void waitACK1()
- {
- int i = ;
- while ()
- {
- if ((Flag[] == && Flag[] == ) || Flag[] == )
- {
- printf("-------------------\n");
- if (Flag[] == ) // Send error package
- {
- printf("RECV: SEND NAK0\n");
- }
- if (Flag[] == ) // Error ACK0 means ACK1
- {
- printf("RECV: Receive package 0\n");
- printf("The data is: ");
- for (i = ; i < DATA_LENGTH; i++)
- printf("%c", pkt_ptr[n_package].data[i]);
- printf("\n");
- printf("RECV: SEND ACK1\n");
- printf("SEND: ACK should be 0\n");
- }
- printf("-------------------\n");
- Flag[] = ; // package error or error ACK can lead to time out
- }
- if (Flag[] == ) // time out
- {
- printf("SEND: Time out\n");
- printf("SEND: Resend package0...\n");
- if (Flag[] == ) // package 1 loss
- {
- Flag[] = ;
- }
- if (Flag[] == ) // ACK 1 loss
- {
- printf("RECV: Detetch the redundant, discard the package1\n");
- Flag[] = ;
- }
- if (Flag[] == ) // package 1 error
- {
- Flag[] = ;
- }
- if (Flag[] == )
- {
- printf("RECV: Detetch the redundant, discard the package1\n");
- Flag[] = ;
- }
- printf("SEND: Start timer\n");
- Flag[] = ;
- }
- if (Flag[] == && Flag[] == && Flag[] == )
- {
- printf("SEND: Stop timer\n");
- printf("-------------------\n");
- printf("RECV: reveive package1\n");
- printf("RECV: send ACK1\n");
- printf("The data is: ");
- for (i = ; i < DATA_LENGTH; i++)
- printf("%c", pkt_ptr[n_package].data[i]);
- printf("\n");
- break;
- }
- }
- }
- void run()
- {
- init();
- while ()
- {
- printf("--------%d package ------------\n", n_package);
- rdt_send0();
- waitACK0();
- n_package++;
- if (n_package == nsimmax)
- break;
- printf("--------%d package ------------\n", n_package);
- rdt_send1();
- waitACK1();
- n_package++;
- if (n_package == nsimmax)
- break;
- }
- return;
- }
- int main(void)
- {
- run();
- return ;
- }
因为是停等协议,所以有两个send函数,有两个wait for ACK函数,都是差不多的,只是一个是发0包,接0包,一个是发1包,接1包。
下面给出运行结果:
按照自己的理解实现比特交换协议(alternating-bit protocol)的更多相关文章
- 社区观点 | 理解比原链MOV链上交换协议
去中心化交换协议的发展 从Bitshare,Stellar到以太坊上的Etherdelta,Bancor,0x协议,去中心化交换协议也经过了好几代发展和很多模式的探索,每一代都通过前面的协议的痛点来进 ...
- 自研DCI网络路由交换协议DCIP-白牌交换机时代的企业网络
一转眼从听华为3Com的路由交换课程到如今已经13年有余了,依稀记得第一节课的时候我带着老婆去听的课(老婆是日语系的.那时还是女朋友,并不懂网络,仅仅是跟着我去上课的).抢了个头排,讲师宋岩老师提问了 ...
- 简易远程消息交换协议SRMP
一.SRMP目标定位 经过十多年实战经验积累以及多方共同讨论,新生命团队(https://github.com/newlifex)制订了一种简单而又具有较好扩展性的RPC(Remote Procedu ...
- 理解分布式一致性:Paxos协议之Generalized Paxos & Byzantine Paxos
理解分布式一致性:Paxos协议之Generalized Paxos & Byzantine Paxos Generalized Paxos Byzantine Paxos Byzantine ...
- 理解分布式一致性:Paxos协议之Cheap Paxos & Fast Paxos
理解分布式一致性:Paxos协议之Cheap Paxos & Fast Paxos Cheap Paxos Message flow: Cheap Multi-Paxos Fast Paxos ...
- 理解分布式一致性:Paxos协议之Multi-Paxos
理解分布式一致性:Paxos协议之Multi-Paxos Multi-Paxos without failures Multi-Paxos when phase 1 can be skipped Mu ...
- 理解分布式一致性:Paxos协议之Basic Paxos
理解分布式一致性:Paxos协议之Basic Paxos 角色 Proposal Number & Agreed Value Basic Paxos Basic Paxos without f ...
- 理解分布式一致性:Raft协议
理解分布式一致性:Raft协议 什么是分布式一致性 Leader选举 日志复制流程 term选举周期 timeout 选举和选举timeout 选举分裂 日志复制和心跳timeout 在分布式系统中, ...
- 浏览器扩展系列————异步可插入协议(pluggable protocol)的实现
原文:浏览器扩展系列----异步可插入协议(pluggable protocol)的实现 IE中有很多我们比较熟悉的协议,如http,https,mailto,ftp等.当然你也可以实现自己定义的协议 ...
随机推荐
- Swift3.0语法变化
写在前面 首先和大家分享一下学习新语法的技巧:用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax- 让Xcod ...
- IOS使用APNS推送Payload字节数限制导致推送不成功
这2天须要在推送上加上脚本,找到了badge方法能够加脚本.加上后可是怎么推送也不成功.郁闷了好久.在网上查找相关资料. 最终被我找到原因: "Payload--最多256bytes. &q ...
- SQL Insert语句数据以以unicode码存储 解决存储数据出现乱码的问题
写了个读取原始的文本数据导入数据库的工具 ,最后发现空中有几个值是乱码 例如 原始数据是 :Bjørn 存到数据库中是 Bj?rn 研究半天发现是一直以来忽略了一个标记‘N’ 2条 Insert 语句 ...
- __asm__ __volatile__("": : :"memory");
参考:http://stackoverflow.com/questions/14950614/working-of-asm-volatile-memory asmvolatile("&quo ...
- HttpClient设置代理,超时,以及得到cookies
import java.net.URI; import java.util.List; import org.apache.http.HttpEntity; import org.apache.htt ...
- Roadblocks http://poj.org/problem?id=3255
Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best ...
- 浅谈xss攻击
近期学习过程中提到xss攻击的问题,便想要了解一下,总结如下: XSS攻击:跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, ...
- Creating a Mono 3 RPM on CentOS
Creating a Mono 3 RPM on CentOS A quick guide to creating an rpm of mono 3 from source, starting wit ...
- 写入文件txt
FileStream fs = new FileStream(@"d:\service.txt", FileMode.OpenOrCreate, FileAccess.Write) ...
- javaweb学习总结八(xml约束DTD)
一:XML约束概念 xml约束:可以编写一个文档来约束xml文件的书写规范. xml语言格式比较严谨,不可能让程序员随意编写,所以必须要有约束. 二:常用的xml约束技术 1:DTD,document ...