一开始的思路是想写两个程序的,发送端和接收端。但是后来想了下,因为是模拟的,所以不用这么麻烦,直接自己定制场景(比如说丢包阿,包出错阿,超时之类的)。

基本上是根据上图所写的,一个函数发包,一个函数接包(比如上图的wait_for_ack0),在这个发包函数里定制场景,在接包函数里处理场景。

说到处理场景,仔细看看wait for ack0上所写的:

 翻译一下:

  1. if ( rdt_rcv(rcvpkt) && (corrupt(rcvpkt)) || isACK(rcvpkt, ) ) // 如果有接受到包且包坏了, 或者接受到的ACK是1,那么就什么都不用做,因为会执行下面的超时函数
  2. {
  3. ;// do nothing,静静地等待超时然后重新发包
  4. }
  1. if (timeout) // 如果超时,重新发包然后重新启动计时器
  2. {
  3. udt_send(sndpkt);
  4. start_timer;
  5. }
  1. if ( rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt, ) ) // 只有凑齐接收到包且包正确且收到的回复正确,那么就可以停止计时了
  2. {
  3. stop timer;
  4. }

因为这是停等协议(stop and wait),所以顺序是先发0包,再发1包,再发0包这样持续下去。

根据场景,我定义了这个一个数组:数据包丢失,确认包丢失,数据包出错,确认包出错,超时 5个场景。 丢失就会超时,出错就是验证校验和。

不过因为我懒,所以没有计算RTT之类的时间,校验和也忽略掉的。

这里给个思路,可以根据公式(大家可以看看计算机网路的书,上面有写算RTT的公式),只要你定义了数据包的大小,网速的话,根据包的个数是可以算出来RTT的。

下面是我自己定义的场景。

  1. #define PACKAGE_LOSS 0
  2. #define ACK_LOSS 1
  3. #define PACK_CORRUPT 2
  4. #define ACK_CORRUPT 3
  5. #define TIME_OUT 4
  6.  
  7. int Flag[] = {}; // 0代表没有,1代表有

你在调用发包这个函数时就询问会出现哪种场景,我写得代码一次发包只能实现一种场景(不过根据场景的不同,有可能引发其他场景。比如丢包,这样自然就会引起超时了)。

在接收包的函数时,就定义解决场景,根据上图写。

下面给出完整代码(有一些地方可能会出错,但也弄出个大概,仅供参考)

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #define DATA_LENGTH 20
  5.  
  6. struct Pkt
  7. {
  8. int seqnum;
  9. int checksum;
  10. char data[DATA_LENGTH];
  11. };
  12.  
  13. #define PACKAGE_LOSS 0
  14. #define ACK_LOSS 1
  15. #define PACK_CORRUPT 2
  16. #define ACK_CORRUPT 3
  17. #define TIME_OUT 4
  18.  
  19. int Flag[] = {};
  20.  
  21. int nsimmax = ; // the number of message
  22. int n_package = ;
  23. struct Pkt *pkt_ptr = NULL;
  24.  
  25. void init()
  26. {
  27. int i = ;
  28. int j = ;
  29. int k = ;
  30.  
  31. printf("---- Stop and Wait Network Simulator Version 1.0 ----\n");
  32. printf("Enter the number of messages to simulate: ");
  33. scanf("%d", &nsimmax);
  34.  
  35. pkt_ptr = (struct Pkt *)malloc(nsimmax * sizeof(struct Pkt)); // nsimmax packages
  36. if (pkt_ptr == NULL)
  37. {
  38. perror("Malloc Error: ");
  39. exit();
  40. }
  41.  
  42. // Fill some data in Pkt.data
  43.  
  44. for (i = ; i < nsimmax; i++)
  45. {
  46. for (j = ; j < DATA_LENGTH; j++)
  47. {
  48. pkt_ptr[i].data[j] = + k;
  49. }
  50.  
  51. k++;
  52. }
  53.  
  54. }
  55.  
  56. void Question(int *p)
  57. {
  58. int i = ;
  59.  
  60. printf("--------------\n");
  61. printf("0 - Nothing wrong\n");
  62. printf("1 - Packet loss\n");
  63. printf("2 - ACK loss\n");
  64. printf("3 - Packet error\n");
  65. printf("4 - ACK error\n");
  66. printf("5 - Time out\n");
  67. printf("--------------\n");
  68.  
  69. printf("Choice: ");
  70. scanf("%d", &i);
  71.  
  72. if (i != )
  73. {
  74. p[i - ] = ;
  75. }
  76. }
  77.  
  78. void send()
  79. {
  80.  
  81. if (Flag[] == )
  82. {
  83. printf("SEND: Package loss\n");
  84. Flag[] = ; // time out
  85. }
  86.  
  87. else if (Flag[] == )
  88. {
  89. printf("SEND: ACK loss\n");
  90. Flag[] = ; // time out
  91. }
  92.  
  93. else if (Flag[] == )
  94. {
  95. printf("SEND: Packet error\n");
  96. }
  97.  
  98. else if (Flag[] == )
  99. {
  100. printf("SEND: ACK error\n");
  101. }
  102.  
  103. else if (Flag[] == )
  104. {
  105. printf("SEND: Time out\n");
  106. }
  107.  
  108. else
  109. {
  110. printf("SEND: Nothing wrong\n");
  111. }
  112.  
  113. printf("\n");
  114.  
  115. }
  116.  
  117. void rdt_send0()
  118. {
  119. Question(Flag);
  120.  
  121. printf("SEND: Send package 0\n");
  122. printf("SEND: Start timer\n\n");
  123.  
  124. send();
  125.  
  126. }
  127.  
  128. void rdt_send1()
  129. {
  130. Question(Flag);
  131.  
  132. printf("SEND: Send package 1\n");
  133. printf("SEND: Start timer\n\n");
  134.  
  135. send();
  136.  
  137. }
  138.  
  139. void waitACK0()
  140. {
  141. int i = ;
  142.  
  143. while ()
  144. {
  145. if ((Flag[] == && Flag[] == ) || Flag[] == )
  146. {
  147. printf("-------------------\n");
  148. if (Flag[] == ) // Send error package
  149. {
  150. printf("RECV: SEND NAK0\n");
  151. }
  152.  
  153. if (Flag[] == ) // Error ACK0 means ACK1
  154. {
  155. printf("RECV: Receive package 0\n");
  156.  
  157. printf("The data is: ");
  158. for (i = ; i < DATA_LENGTH; i++)
  159. printf("%c", pkt_ptr[n_package].data[i]);
  160. printf("\n");
  161.  
  162. printf("RECV: SEND ACK1\n");
  163. printf("SEND: ACK should be 0\n");
  164. }
  165. printf("-------------------\n");
  166.  
  167. Flag[] = ; // package error or error ACK can lead to time out
  168. }
  169.  
  170. if (Flag[] == ) // time out
  171. {
  172. printf("SEND: Time out\n");
  173. printf("SEND: Resend package0...\n");
  174. if (Flag[] == ) // package 0 loss
  175. {
  176. Flag[] = ;
  177. }
  178.  
  179. if (Flag[] == ) // ACK 0 loss
  180. {
  181. printf("RECV: Detetch the redundant, discard the package0\n");
  182. Flag[] = ;
  183. }
  184.  
  185. if (Flag[] == ) // package 0 error
  186. {
  187. Flag[] = ;
  188. }
  189.  
  190. if (Flag[] == )
  191. {
  192. printf("RECV: Detetch the redundant, discard the package0\n");
  193. Flag[] = ;
  194. }
  195.  
  196. printf("SEND: Start timer\n");
  197. Flag[] = ;
  198. }
  199.  
  200. if (Flag[] == && Flag[] == && Flag[] == )
  201. {
  202. printf("SEND: Stop timer\n");
  203. printf("-------------------\n");
  204. printf("RECV: reveive package0\n");
  205. printf("RECV: send ACK0\n");
  206.  
  207. printf("The data is: ");
  208. for (i = ; i < DATA_LENGTH; i++)
  209. printf("%c", pkt_ptr[n_package].data[i]);
  210. printf("\n");
  211.  
  212. break;
  213. }
  214. }
  215. }
  216.  
  217. void waitACK1()
  218. {
  219. int i = ;
  220.  
  221. while ()
  222. {
  223. if ((Flag[] == && Flag[] == ) || Flag[] == )
  224. {
  225. printf("-------------------\n");
  226. if (Flag[] == ) // Send error package
  227. {
  228. printf("RECV: SEND NAK0\n");
  229. }
  230.  
  231. if (Flag[] == ) // Error ACK0 means ACK1
  232. {
  233. printf("RECV: Receive package 0\n");
  234.  
  235. printf("The data is: ");
  236. for (i = ; i < DATA_LENGTH; i++)
  237. printf("%c", pkt_ptr[n_package].data[i]);
  238. printf("\n");
  239.  
  240. printf("RECV: SEND ACK1\n");
  241. printf("SEND: ACK should be 0\n");
  242. }
  243. printf("-------------------\n");
  244.  
  245. Flag[] = ; // package error or error ACK can lead to time out
  246. }
  247.  
  248. if (Flag[] == ) // time out
  249. {
  250. printf("SEND: Time out\n");
  251. printf("SEND: Resend package0...\n");
  252. if (Flag[] == ) // package 1 loss
  253. {
  254. Flag[] = ;
  255. }
  256.  
  257. if (Flag[] == ) // ACK 1 loss
  258. {
  259. printf("RECV: Detetch the redundant, discard the package1\n");
  260. Flag[] = ;
  261. }
  262.  
  263. if (Flag[] == ) // package 1 error
  264. {
  265. Flag[] = ;
  266. }
  267.  
  268. if (Flag[] == )
  269. {
  270. printf("RECV: Detetch the redundant, discard the package1\n");
  271. Flag[] = ;
  272. }
  273.  
  274. printf("SEND: Start timer\n");
  275. Flag[] = ;
  276. }
  277.  
  278. if (Flag[] == && Flag[] == && Flag[] == )
  279. {
  280. printf("SEND: Stop timer\n");
  281. printf("-------------------\n");
  282. printf("RECV: reveive package1\n");
  283. printf("RECV: send ACK1\n");
  284.  
  285. printf("The data is: ");
  286. for (i = ; i < DATA_LENGTH; i++)
  287. printf("%c", pkt_ptr[n_package].data[i]);
  288. printf("\n");
  289.  
  290. break;
  291. }
  292. }
  293. }
  294.  
  295. void run()
  296. {
  297. init();
  298. while ()
  299. {
  300. printf("--------%d package ------------\n", n_package);
  301. rdt_send0();
  302. waitACK0();
  303. n_package++;
  304. if (n_package == nsimmax)
  305. break;
  306.  
  307. printf("--------%d package ------------\n", n_package);
  308. rdt_send1();
  309. waitACK1();
  310. n_package++;
  311.  
  312. if (n_package == nsimmax)
  313. break;
  314. }
  315.  
  316. return;
  317.  
  318. }
  319.  
  320. int main(void)
  321. {
  322. run();
  323. return ;
  324. }

因为是停等协议,所以有两个send函数,有两个wait for ACK函数,都是差不多的,只是一个是发0包,接0包,一个是发1包,接1包。

下面给出运行结果:

按照自己的理解实现比特交换协议(alternating-bit protocol)的更多相关文章

  1. 社区观点 | 理解比原链MOV链上交换协议

    去中心化交换协议的发展 从Bitshare,Stellar到以太坊上的Etherdelta,Bancor,0x协议,去中心化交换协议也经过了好几代发展和很多模式的探索,每一代都通过前面的协议的痛点来进 ...

  2. 自研DCI网络路由交换协议DCIP-白牌交换机时代的企业网络

    一转眼从听华为3Com的路由交换课程到如今已经13年有余了,依稀记得第一节课的时候我带着老婆去听的课(老婆是日语系的.那时还是女朋友,并不懂网络,仅仅是跟着我去上课的).抢了个头排,讲师宋岩老师提问了 ...

  3. 简易远程消息交换协议SRMP

    一.SRMP目标定位 经过十多年实战经验积累以及多方共同讨论,新生命团队(https://github.com/newlifex)制订了一种简单而又具有较好扩展性的RPC(Remote Procedu ...

  4. 理解分布式一致性:Paxos协议之Generalized Paxos & Byzantine Paxos

    理解分布式一致性:Paxos协议之Generalized Paxos & Byzantine Paxos Generalized Paxos Byzantine Paxos Byzantine ...

  5. 理解分布式一致性:Paxos协议之Cheap Paxos & Fast Paxos

    理解分布式一致性:Paxos协议之Cheap Paxos & Fast Paxos Cheap Paxos Message flow: Cheap Multi-Paxos Fast Paxos ...

  6. 理解分布式一致性:Paxos协议之Multi-Paxos

    理解分布式一致性:Paxos协议之Multi-Paxos Multi-Paxos without failures Multi-Paxos when phase 1 can be skipped Mu ...

  7. 理解分布式一致性:Paxos协议之Basic Paxos

    理解分布式一致性:Paxos协议之Basic Paxos 角色 Proposal Number & Agreed Value Basic Paxos Basic Paxos without f ...

  8. 理解分布式一致性:Raft协议

    理解分布式一致性:Raft协议 什么是分布式一致性 Leader选举 日志复制流程 term选举周期 timeout 选举和选举timeout 选举分裂 日志复制和心跳timeout 在分布式系统中, ...

  9. 浏览器扩展系列————异步可插入协议(pluggable protocol)的实现

    原文:浏览器扩展系列----异步可插入协议(pluggable protocol)的实现 IE中有很多我们比较熟悉的协议,如http,https,mailto,ftp等.当然你也可以实现自己定义的协议 ...

随机推荐

  1. Swift3.0语法变化

    写在前面 首先和大家分享一下学习新语法的技巧:用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax- 让Xcod ...

  2. IOS使用APNS推送Payload字节数限制导致推送不成功

    这2天须要在推送上加上脚本,找到了badge方法能够加脚本.加上后可是怎么推送也不成功.郁闷了好久.在网上查找相关资料. 最终被我找到原因: "Payload--最多256bytes. &q ...

  3. SQL Insert语句数据以以unicode码存储 解决存储数据出现乱码的问题

    写了个读取原始的文本数据导入数据库的工具 ,最后发现空中有几个值是乱码 例如 原始数据是 :Bjørn 存到数据库中是 Bj?rn 研究半天发现是一直以来忽略了一个标记‘N’ 2条 Insert 语句 ...

  4. __asm__ __volatile__("": : :"memory");

    参考:http://stackoverflow.com/questions/14950614/working-of-asm-volatile-memory asmvolatile("&quo ...

  5. HttpClient设置代理,超时,以及得到cookies

    import java.net.URI; import java.util.List; import org.apache.http.HttpEntity; import org.apache.htt ...

  6. 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 ...

  7. 浅谈xss攻击

    近期学习过程中提到xss攻击的问题,便想要了解一下,总结如下: XSS攻击:跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, ...

  8. 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 ...

  9. 写入文件txt

    FileStream fs = new FileStream(@"d:\service.txt", FileMode.OpenOrCreate, FileAccess.Write) ...

  10. javaweb学习总结八(xml约束DTD)

    一:XML约束概念 xml约束:可以编写一个文档来约束xml文件的书写规范. xml语言格式比较严谨,不可能让程序员随意编写,所以必须要有约束. 二:常用的xml约束技术 1:DTD,document ...