按照自己的理解实现比特交换协议(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 ----\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(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("--------------\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 != 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\n");
 84         Flag[4] = 1; // time out
 85     }
 86 
 87     else if (Flag[1] == 1)
 88     {
 89         printf("SEND: ACK loss\n");
 90         Flag[4] = 1; // time out
 91     }
 92 
 93     else if (Flag[2] == 1)
 94     {
 95         printf("SEND: Packet error\n");
 96     }
 97 
 98     else if (Flag[3] == 1)
 99     {
100         printf("SEND: ACK error\n");
101     }
102 
103     else if (Flag[4] == 1)
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 
118 void rdt_send0()
119 {
120     Question(Flag);
121 
122     printf("SEND: Send package 0\n");
123     printf("SEND: Start timer\n\n");
124     
125     send();
126 
127 }
128 
129 void rdt_send1()
130 {
131     Question(Flag);
132 
133     printf("SEND: Send package 1\n");
134     printf("SEND: Start timer\n\n");
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("-------------------\n");
149             if (Flag[2] == 1) // Send error package
150             {
151                 printf("RECV: SEND NAK0\n"); 
152             }
153 
154             if (Flag[3] == 1) // Error ACK0 means ACK1
155             {
156                 printf("RECV: Receive package 0\n");
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("\n");
162 
163                 printf("RECV: SEND ACK1\n"); 
164                 printf("SEND: ACK should be 0\n");
165             }
166             printf("-------------------\n");
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\n");
174             printf("SEND: Resend package0...\n");
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\n");
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\n");
194                 Flag[3] = 0;
195             }
196 
197             printf("SEND: Start timer\n");
198             Flag[4] = 0;
199         }
200 
201         if (Flag[0] == 0 && Flag[2] == 0 && Flag[3] == 0)
202         {
203             printf("SEND: Stop timer\n");
204             printf("-------------------\n");
205             printf("RECV: reveive package0\n");
206             printf("RECV: send ACK0\n");
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("\n");
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("-------------------\n");
228             if (Flag[2] == 1) // Send error package
229             {
230                 printf("RECV: SEND NAK0\n"); 
231             }
232 
233             if (Flag[3] == 1) // Error ACK0 means ACK1
234             {
235                 printf("RECV: Receive package 0\n");
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("\n");
241 
242                 printf("RECV: SEND ACK1\n"); 
243                 printf("SEND: ACK should be 0\n");
244             }
245             printf("-------------------\n");
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\n");
253             printf("SEND: Resend package0...\n");
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\n");
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\n");
273                 Flag[3] = 0;
274             }
275 
276             printf("SEND: Start timer\n");
277             Flag[4] = 0;
278         }
279 
280 
281         if (Flag[0] == 0 && Flag[2] == 0 && Flag[3] == 0)
282         {
283             printf("SEND: Stop timer\n");
284             printf("-------------------\n");
285             printf("RECV: reveive package1\n");
286             printf("RECV: send ACK1\n");
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("\n");
292 
293             break;
294         }
295     }
296 }
297 
298 void run()
299 {    
300     init();
301     while (1)
302     {
303         printf("--------%d package ------------\n", n_package);
304         rdt_send0();
305         waitACK0();
306         n_package++;
307         if (n_package == nsimmax)
308             break;
309 
310         printf("--------%d package ------------\n", 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包。

下面给出运行结果:

 

posted on 2015-11-11 21:49  fusae  阅读(4249)  评论(0编辑  收藏  举报

导航