一開始的思路是想寫兩個程序的,發送端和接收端。可是後來想了下,由於是模擬的,因此不用這麼麻煩,直接本身定製場景(好比說丟包阿,包出錯阿,超時之類的)。數組
基本上是根據上圖所寫的,一個函數發包,一個函數接包(好比上圖的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 }
由於是停等協議,因此有兩個send函數,有兩個wait for ACK函數,都是差很少的,只是一個是發0包,接0包,一個是發1包,接1包。
下面給出運行結果: