按照本身的理解實現比特交換協議(alternating-bit protocol)

一開始的思路是想寫兩個程序的,發送端和接收端。可是後來想了下,由於是模擬的,因此不用這麼麻煩,直接本身定製場景(好比說丟包阿,包出錯阿,超時之類的)。數組

基本上是根據上圖所寫的,一個函數發包,一個函數接包(好比上圖的wait_for_ack0),在這個發包函數裏定製場景,在接包函數裏處理場景。ide

說處處理場景,仔細看看wait for ack0上所寫的:函數

 翻譯一下:spa

 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個場景。 丟失就會超時,出錯就是驗證校驗和。code

不過由於我懶,因此沒有計算RTT之類的時間,校驗和也忽略掉的。blog

這裏給個思路,能夠根據公式(你們能夠看看計算機網路的書,上面有寫算RTT的公式),只要你定義了數據包的大小,網速的話,根據包的個數是能夠算出來RTT的。it

下面是我本身定義的場景。io

#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表明有

你在調用發包這個函數時就詢問會出現哪一種場景,我寫得代碼一次發包只能實現一種場景(不過根據場景的不一樣,有可能引起其餘場景。好比丟包,這樣天然就會引發超時了)。event

在接收包的函數時,就定義解決場景,根據上圖寫。

 

下面給出完整代碼(有一些地方可能會出錯,但也弄出個大概,僅供參考)

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包。

下面給出運行結果:

相關文章
相關標籤/搜索