zoukankan      html  css  js  c++  java
  • 按照自己的理解实现比特交换协议(alternating-bit protocol)

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

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

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

     翻译一下:

     if ( rdt_rcv(rcvpkt) && (corrupt(rcvpkt)) || isACK(rcvpkt, 1) )  // 如果有接受到包且包坏了, 或者接受到的ACK是1,那么就什么都不用做,因为会执行下面的超时函数
    {
        ;// do nothing,静静地等待超时然后重新发包      
    }
    if (timeout) // 如果超时,重新发包然后重新启动计时器
    {
        udt_send(sndpkt);
        start_timer;      
    }
    if ( rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt, 0) ) // 只有凑齐接收到包且包正确且收到的回复正确,那么就可以停止计时了
    {
        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[5] = {0}; // 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[5] = {0};
     20 
     21 int nsimmax = 0; // the number of message
     22 int n_package = 0;
     23 struct Pkt *pkt_ptr = NULL;
     24 
     25 void init()
     26 {
     27     int i = 0;
     28     int j = 0;
     29     int k = 0;
     30 
     31     printf("---- Stop and Wait Network Simulator Version 1.0 ----
    ");
     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(1);
     40     }
     41 
     42     // Fill some data in Pkt.data
     43     
     44     for (i = 0; i < nsimmax; i++)
     45     {
     46         for (j = 0; j < DATA_LENGTH; j++)        
     47         {
     48             pkt_ptr[i].data[j] = 97 + k;
     49         }
     50 
     51         k++;
     52     }
     53     
     54 }
     55 
     56 void Question(int *p)
     57 {
     58     int i = 0;
     59 
     60     printf("--------------
    ");
     61     printf("0 - Nothing wrong
    ");
     62     printf("1 - Packet loss
    ");
     63     printf("2 - ACK loss
    ");
     64     printf("3 - Packet error
    ");
     65     printf("4 - ACK error
    ");
     66     printf("5 - Time out
    ");
     67     printf("--------------
    ");
     68 
     69     printf("Choice: ");
     70     scanf("%d", &i);
     71 
     72     if (i != 0)
     73     {
     74         p[i - 1] = 1;
     75     }
     76 }
     77 
     78 void send()
     79 {
     80 
     81     if (Flag[0] == 1)
     82     {
     83         printf("SEND: Package loss
    ");
     84         Flag[4] = 1; // time out
     85     }
     86 
     87     else if (Flag[1] == 1)
     88     {
     89         printf("SEND: ACK loss
    ");
     90         Flag[4] = 1; // time out
     91     }
     92 
     93     else if (Flag[2] == 1)
     94     {
     95         printf("SEND: Packet error
    ");
     96     }
     97 
     98     else if (Flag[3] == 1)
     99     {
    100         printf("SEND: ACK error
    ");
    101     }
    102 
    103     else if (Flag[4] == 1)
    104     {
    105         printf("SEND: Time out
    ");        
    106     }
    107 
    108     else
    109     {
    110         printf("SEND: Nothing wrong
    ");
    111     }
    112 
    113     printf("
    ");
    114 
    115     
    116 }
    117 
    118 void rdt_send0()
    119 {
    120     Question(Flag);
    121 
    122     printf("SEND: Send package 0
    ");
    123     printf("SEND: Start timer
    
    ");
    124     
    125     send();
    126 
    127 }
    128 
    129 void rdt_send1()
    130 {
    131     Question(Flag);
    132 
    133     printf("SEND: Send package 1
    ");
    134     printf("SEND: Start timer
    
    ");
    135 
    136     send();
    137 
    138 }
    139 
    140 void waitACK0()
    141 {
    142     int i = 0;
    143 
    144     while (1)
    145     {
    146         if ((Flag[0] == 0 && Flag[2] == 1) || Flag[3] == 1)
    147         {
    148             printf("-------------------
    ");
    149             if (Flag[2] == 1) // Send error package
    150             {
    151                 printf("RECV: SEND NAK0
    "); 
    152             }
    153 
    154             if (Flag[3] == 1) // Error ACK0 means ACK1
    155             {
    156                 printf("RECV: Receive package 0
    ");
    157 
    158                 printf("The data is: ");
    159                 for (i = 0; i < DATA_LENGTH; i++)
    160                     printf("%c", pkt_ptr[n_package].data[i]);
    161                 printf("
    ");
    162 
    163                 printf("RECV: SEND ACK1
    "); 
    164                 printf("SEND: ACK should be 0
    ");
    165             }
    166             printf("-------------------
    ");
    167 
    168             Flag[4] = 1; // package error or error ACK can lead to time out
    169         }
    170             
    171         if (Flag[4] == 1) // time out
    172         {
    173             printf("SEND: Time out
    ");
    174             printf("SEND: Resend package0...
    ");
    175             if (Flag[0] == 1) // package 0 loss
    176             {
    177                 Flag[0] = 0;
    178             }
    179 
    180             if (Flag[1] == 1) // ACK 0 loss
    181             {
    182                 printf("RECV: Detetch the redundant, discard the package0
    ");
    183                 Flag[1] = 0;
    184             }
    185 
    186             if (Flag[2] == 1) // package 0 error
    187             {
    188                 Flag[2] = 0;
    189             }
    190 
    191             if (Flag[3] == 1)
    192             {
    193                 printf("RECV: Detetch the redundant, discard the package0
    ");
    194                 Flag[3] = 0;
    195             }
    196 
    197             printf("SEND: Start timer
    ");
    198             Flag[4] = 0;
    199         }
    200 
    201         if (Flag[0] == 0 && Flag[2] == 0 && Flag[3] == 0)
    202         {
    203             printf("SEND: Stop timer
    ");
    204             printf("-------------------
    ");
    205             printf("RECV: reveive package0
    ");
    206             printf("RECV: send ACK0
    ");
    207 
    208             printf("The data is: ");
    209             for (i = 0; i < DATA_LENGTH; i++)
    210                 printf("%c", pkt_ptr[n_package].data[i]);
    211             printf("
    ");
    212 
    213             break;
    214         }
    215     }
    216 }
    217 
    218 
    219 void waitACK1()
    220 {
    221     int i = 0;
    222 
    223     while (1)
    224     {
    225         if ((Flag[0] == 0 && Flag[2] == 1) || Flag[3] == 1)
    226         {
    227             printf("-------------------
    ");
    228             if (Flag[2] == 1) // Send error package
    229             {
    230                 printf("RECV: SEND NAK0
    "); 
    231             }
    232 
    233             if (Flag[3] == 1) // Error ACK0 means ACK1
    234             {
    235                 printf("RECV: Receive package 0
    ");
    236 
    237                 printf("The data is: ");
    238                 for (i = 0; i < DATA_LENGTH; i++)
    239                     printf("%c", pkt_ptr[n_package].data[i]);
    240                 printf("
    ");
    241 
    242                 printf("RECV: SEND ACK1
    "); 
    243                 printf("SEND: ACK should be 0
    ");
    244             }
    245             printf("-------------------
    ");
    246 
    247             Flag[4] = 1; // package error or error ACK can lead to time out
    248         }
    249             
    250         if (Flag[4] == 1) // time out
    251         {
    252             printf("SEND: Time out
    ");
    253             printf("SEND: Resend package0...
    ");
    254             if (Flag[0] == 1) // package 1 loss
    255             {
    256                 Flag[0] = 0;
    257             }
    258 
    259             if (Flag[1] == 1) // ACK 1 loss
    260             {
    261                 printf("RECV: Detetch the redundant, discard the package1
    ");
    262                 Flag[1] = 0;
    263             }
    264 
    265             if (Flag[2] == 1) // package 1 error
    266             {
    267                 Flag[2] = 0;
    268             }
    269 
    270             if (Flag[3] == 1)
    271             {
    272                 printf("RECV: Detetch the redundant, discard the package1
    ");
    273                 Flag[3] = 0;
    274             }
    275 
    276             printf("SEND: Start timer
    ");
    277             Flag[4] = 0;
    278         }
    279 
    280 
    281         if (Flag[0] == 0 && Flag[2] == 0 && Flag[3] == 0)
    282         {
    283             printf("SEND: Stop timer
    ");
    284             printf("-------------------
    ");
    285             printf("RECV: reveive package1
    ");
    286             printf("RECV: send ACK1
    ");
    287 
    288             printf("The data is: ");
    289             for (i = 0; i < DATA_LENGTH; i++)
    290                 printf("%c", pkt_ptr[n_package].data[i]);
    291             printf("
    ");
    292 
    293             break;
    294         }
    295     }
    296 }
    297 
    298 void run()
    299 {    
    300     init();
    301     while (1)
    302     {
    303         printf("--------%d package ------------
    ", n_package);
    304         rdt_send0();
    305         waitACK0();
    306         n_package++;
    307         if (n_package == nsimmax)
    308             break;
    309 
    310         printf("--------%d package ------------
    ", n_package);
    311         rdt_send1();
    312         waitACK1();
    313         n_package++;
    314 
    315         if (n_package == nsimmax)
    316             break;
    317     }
    318 
    319     return;
    320 
    321 }
    322 
    323 int main(void)
    324 {
    325     run();
    326     return 0;
    327 }
    View Code

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

    下面给出运行结果:

  • 相关阅读:
    jboss hello world
    jboss 7 启动问题
    jboss [how to access the admin console]
    tomee 消息持久化
    Python、C和Java对比
    编程语言产生时间表
    从关系型数据库到非关系型数据库
    约束和异常处理
    类与类之间的关系
    类的成员
  • 原文地址:https://www.cnblogs.com/fusae-blog/p/4957442.html
Copyright © 2011-2022 走看看