按照自己的理解實現比特交換協議(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包。

下面給出運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM