Saturday, June 8, 2013

Phase 7 - Implement Sliding WIndow (Part 3)

What to do

  • Phase 5 and Phase 6 are more like the preparation for implementing selective repeat. In Phase 7, we will get into the actual mechanism of selective repeat. Because selective repeat protocol is very complicated, it is almost impossible to implement it in one step without any error, we need to divide the whole work into smaller steps, and validate the code at each step. Below is how I divide the work:
========================================= Step 1 ============================================
Make things simple
  • Window size at both client and server to be 1.
  • No frame loss and all the frames received are correct, thus no need to consider retransmission. 
  • Send ACK frame back to sender as soon as the receiver receives a frame. No need to implement timeout and ack_timeout event yet. 
We've already limit the complexity, now the only tricky thing left is how to achieve the flow control between Applcation Layer and Datalink Layer, as we only want to enable application layer when nbuffered < NR_BUFS. The first idea that came to my mind is to use signaling between processes; just suspend the Application Layer whenever before a packet is going to be written to the pipe. The Application Layer resumes when it receives a signal from Datalink Layer, which is generated by calling the function enable_app_layer(). Unfortunately, this approach does not work because the signal needs to been generated after the suspension of the Application Layer, otherwise that signal will just be ignored and the application layer will be suspended forever. An alternative is to use select() to block the Application Layer at the same place where it is suspended in the previous approach. The select() monitors the pipe, when receiving a control packet, it unblock the application layer, letting application layer continue writing to the pipe. The control packet is generated and sent to the pipe when calling enable_app_layer(). At this point, the Application Layer is blocked, either waiting to send packets or waiting for incoming packets. Note that the control packet may be consumed sometimes when the Application Layer is waiting for some data packet to come. If control packet is consumed under this situation, they won't have effect on the Application Layer.

Variables
There are a bunch of variables used in selective repeat protocol. They are declared and initialized at both client and server end. Notice that, they are not used at the same time. out_buf[NR_BUFS], nbuffered, next_frame_to_send, and ack_expected are the ones used at the sender, and arrived[NR_BUFS], in_buf[NR_BUFS], frame_expected, and to_far are used at the receiver. Because client and server could act as both a sender and recevier, all these variables will be used eventually. 

Structure Graph (Step 1)

Validation
It's a good idea to test the code by using files of different sizes. Large files are more likely to break down the program, making them the better test cases. For me, I use four files to validate the correctness of the code written so far. 
  • image.jpeg - 457 bytes
  • image.jpg - 606KB 
  • music.mp3 - 4.73MB
  • test.rar - 123MB

========================================= Step 2 ============================================
Make things simple
  • Introduce checksum error and NAK frame, but still assume there is no frame loss. Thus no need to consider timeout and ack_timeout event yet. 
  • Assume that we could only insert error into DATA frame at client side, i.e. no errors in ACK, NAK frame, and DATA frames sent by server. 
  • Follow one extra rule: frame is inserted an error the first time it is sent to the receiver, when in re-transmission, no error is inserted into that frame.
Making the above simplification, we are able to introduce NAK frame at Step 2 without using any timer. Below is the result when uploading the file image.jpeg.

Client Output

Please type in command here: UP#image.jpeg#
-> 1 frame: DATA (Error)
<- 1 frame: NAK
-> 2 frame: DATA (Retransmission)
<- 2 frame: ACK
<- 3 frame: DATA
-> 3 frame: ACK
Start uploading...
-> 4 frame: DATA (Error)
<- 4 frame: NAK
-> 5 frame: DATA (Retransmission)
<- 5 frame: ACK
-> 6 frame: DATA (Error)
<- 6 frame: NAK
-> 7 frame: DATA (Retransmission)
<- 7 frame: ACK
-> 8 frame: DATA (Error)
<- 8 frame: NAK
-> 9 frame: DATA (Retransmission)
<- 9 frame: ACK
-> 10 frame: DATA (Error)
<- 10 frame: NAK
-> 11 frame: DATA (Retransmission)
<- 11 frame: ACK
<- 12 frame: DATA
-> 12 frame: ACK
You've uploaded the file

Server Output


<- 1 frame: DATA (BAD)
-> 1 frame: NAK
<- 2 frame: DATA (GOOD)
-> 2 frame: ACK
-> 3 frame: DATA 
<- 3 frame: ACK

<- 4 frame: DATA (BAD)
-> 4 frame: NAK
<- 5 frame: DATA (GOOD)
<- 5 frame: ACK
<- 6 frame: DATA (BAD)
-> 6 frame: NAK
<- 7 frame: DATA (GOOD)
-> 7 frame: ACK
<- 8 frame: DATA (BAD)
-> 8 frame: NAK
<- 9 frame: DATA (GOOD)
-> 9 frame: ACK
<- 10 frame: DATA (BAD)
-> 10 frame: NAK
<- 11 frame: DATA (GOOD)
-> 11 frame: ACK
-> 12 frame: DATA
<- 12 frame: ACK




































========================================= Step 3 ============================================
Our task in Step 3 is to realize timer for sender. When a timer times out, the sender knows that a DATA frame it sent previously is lost, or the ACK frame to that DATA frame is lost while in transmission. In response to a timeout event, the sender retransmits the DATA frame corresponding to the timer. How to implement the timer is another piece of work in Selective Repeat protocol. First of all, the timers we are going to implement is virtual timers, which are different from the system timer each process has, and it could not be as accurate as the real timer. Thus we need to use the single timer to simulate multiple virtual timers (at this step, we only need to implement one virtual timer because for now the window size at the sender is 1). Second,  how to tell the program that a timer times out is yet another problem we need to face. To solve the first problem, page 222, 223 on the textbook is a good place to find inspiration. What I ended up doing is to use array. Each entry of the array represents a timer and the number in the entry stands for the time left to this timer, with -1 meaning this timer hasn't been started yet or has been stopped. As the system clock ticks, the number in each entry (if not equal to -1) is decremented by a certain time interval, and then if the number in that entry becomes 0, a timeout signal will be sent to Datalink Layer. Another important thing I need to mention is we cannot put timers in Datalink Layer or Application Layer, we need to create another process (let's call it Timer Process), in which we "put" all of our timers. For the second problem, since we used function select() through this project, there will be no exception here. We will create two extra pipes. One pipe is for the Datalink Layer to send starting timer or stopping timer signal to Timer process, and another pipe is for Timer process to send timeout signal to Datalink Layer.   

For the timer signals, we used a simple structure which contains three members, timer_NO, type and command. timer_NO is the index of the timer (entry of the array), type could be either TO (timeout) or ATO (ACK timeout), and command could be START, STOP or TIMEOUT. The structure is shown below.
struct timeout_sig{
unsigned int timer_NO;
timer_type type;
        timer_command command; };

The following textbox shows the output of transmitting image.jpeg from Client to Server
Client ERRORRATE = 70%
Server ERRORRATE = 0%
Tick = 0.1 milisecond
Timer Interval = 50 milisecond
ACKTimer Interval = 1 milisecond

Output of client

  1. Please type in command here: UP#image.jpeg#
  2. -> 1 frame: DATA (BAD)
  3. <- 1 frame: NAK
  4. -> 2 frame: DATA (Retransmission) (BAD)
  5. Timeout 1
  6. -> 3 frame: DATA (Retransmission) (BAD)
  7. Timeout 2
  8. -> 4 frame: DATA (Retransmission) (GOOD)
  9. <- 2 frame: ACK
  10. <- 3 frame: DATA
  11. -> 5 frame: ACK
  12. Start uploading...
  13. -> 6 frame: DATA (GOOD)
  14. <- 4 frame: ACK
  15. -> 7 frame: DATA (GOOD)
  16. <- 5 frame: ACK
  17. -> 8 frame: DATA (GOOD)
  18. <- 6 frame: ACK
  19. -> 9 frame: DATA (BAD)
  20. <- 7 frame: NAK
  21. -> 10 frame: DATA (Retransmission) (BAD)
  22. Timeout 3
  23. -> 11 frame: DATA (Retransmission) (GOOD)
  24. <- 8 frame: ACK
  25. <- 9 frame: DATA
  26. -> 12 frame: ACK
  27. You've uploadeded the file

Output of server


  1. <- 1 frame: DATA - BAD
  2. -> 1 frame: NAK
  3. <- 2 frame: DATA - BAD

  4. <- 3 frame: DATA - BAD

  5. <- 4 frame: DATA - GOOD
  6. -> 2 frame: ACK
  7. -> 3 frame: DATA
  8. <- 5 frame: ACK

  9. <- 6 frame: DATA - GOOD
  10. -> 4 frame: ACK
  11. <- 7 frame: DATA - GOOD
  12. -> 5 frame: ACK
  13. <- 8 frame: DATA - GOOD
  14. -> 6 frame: ACK
  15. <- 9 frame: DATA - BAD
  16. -> 7 frame: NAK
  17. <- 10 frame: DATA - BAD

  18. <- 11 frame: DATA - GOOD
  19. -> 8 frame: ACK
  20. -> 9 frame: DATA
  21. <- 12 frame: ACK


































Now we know that timer works. Is it done for  step 3? No, there is one more thing you need to decide, i.e. we need to specify how long a "tick" will be and how long before a timer timesout. In my code, a "tick" is 1 milisecond and timer will timeout after 0.5 second. These are pretty large numbers if timeout event is frequent, but are fairly reasonable  numbers if you just play around with the program. So decide carefully on these two numbers.

Structure Graph (Step 3)

There are still a bunch of simplification in Step 3. As we go forward, we will continuously add complexity. The simplification at Step 3 is all the ACK frame or NAK frame contain no error and will not be lost during transmission, and all the frames sent by server contain no error and will not be lost during transmission.

========================================= Step 4 ============================================
At Step 4, we are going to implement ACK timer. Because of ACK timer, the receiver does not need to send back the ACK frame corresponding to each data frame it receives. For more details about why ACK timer is used, please take a look at page 227, 228 of the textbook. In short, as long as there is some reverse traffic (data frame or NAK frame) back to the sender before the ACK timer expires, the ACK timer will be stopped and thus the ACK will be held. Here is how the textbook put it - If no reverse traffic has presented itself before this timer expires, a separate acknowledgement frame is sent.
Implementing ACK timer is much easier than the retransmission timer. First, all the hard stuff has been finished at Step 3, i.e. we just need to put the ACK timer in the same Timer Process, using the same pipes to send timeout signals and receive start/stop signals. Second, no matter how many window size you have, there is only one ACK timer. So using an integer variable to represent the ACK timer is enough, and the ACK timer works just the same as the retransmission timer. One important difference, maybe obvious enough, between retransmission timer and ACK timer is that ACK timer is used for receiver, and retransmission timer is used for sender. Also make sure the timeout associated with the auxiliary timer be appreciably shorter than the timer used for timing out data frames. This condition is required to make sure a correctly received frame  is acknowledged early enough that the frame's retransmission timer does not expire and retransmit the frame.

========================================= Step 5 ============================================
From Step 1 to 4, we made certain assumptions to simplify the implementation of Selective Repeat protocol. One of these assumptions is that all the ACK and NAK frame contains no error. In Step 5 we are going to make sure our program could deal with erroneous ACK and NAK frame. In fact, the receiver does not do anything upon receiving damaged ACK or NAK frame, which is fine because we have retransmission timer that will make sure the DATA frame will be retransmitted if it's not been acknowledged within certain period. Another thing I want to mention is that the receiver will respond differently to incoming frames that contain no error. For example, for a DATA frame that is not the one the receiver is expecting, whether or not a NAK frame has been sent makes a difference; if no NAK frame has been sent, the receiver will send a NAK frame to sender. While if a NAK frame has already been sent, the receiver will do nothing. The second goal of Step 5 is to make sure the server program shares exactly the same Datalink code with the client program by implementing retransmission timers and ACK timer at Server side. At this point, we have a client and server that shares the same code of Datalink Layer, yet different code of Application Layer. 


The following textbox shows the output of transmitting image.jpeg from Client to Server using the configuration below
Client ERRORRATE = 60%
Server ERRORRATE = 0%
Tick = 0.1 milisecond
Timer Interval = 50 milisecond
ACKTimer Interval = 1 milisecond

Client Output

  1. Please type in command here: UP#image.jpeg#
  2. -> 1 frame: DATA (BAD)
  3. Start Timer
  4. Stop ACK Timer
  5. <- 1 frame: NAK (GOOD) (BETWEEN)

  6. -> 2 frame: DATA (Retransmission) (BAD)
  7. Start Timer
  8. Stop ACK Timer
  9. Timeout 1
  10. -> 3 frame: DATA (Retransmission) (GOOD)
  11. Start Timer
  12. Stop ACK Timer
  13. <- 2 frame: DATA (GOOD) (EXPECTED)
  14. Start ACK Timer
  15. Start uploading...
  16. Ack timeout 1
  17. -> 4 frame: ACK (GOOD)
  18. Stop ACK Timer
  19. Timeout 2
  20. -> 5 frame: DATA (Retransmission) (BAD)
  21. Start Timer
  22. Stop ACK Timer
  23. <- 3 frame: NAK (GOOD) (NOT BETWEEN)
  24. Timeout 3
  25. -> 6 frame: DATA (Retransmission) (GOOD)
  26. Start Timer
  27. Stop ACK Timer
  28. <- 4 frame: ACK (GOOD)
  29. Stop Timer
  30. -> 7 frame: DATA (GOOD)
  31. Start Timer
  32. Stop ACK Timer
  33. <- 5 frame: ACK (GOOD)
  34. Stop Timer
  35. -> 8 frame: DATA (GOOD)
  36. Start Timer
  37. Stop ACK Timer
  38. <- 6 frame: ACK (GOOD)
  39. Stop Timer
  40. -> 9 frame: DATA (BAD)
  41. Start Timer
  42. Stop ACK Timer
  43. <- 7 frame: NAK (GOOD) (BETWEEN)

  44. -> 10 frame: DATA (Retransmission) (BAD)
  45. Start Timer
  46. Stop ACK Timer
  47. Timeout 4
  48. -> 11 frame: DATA (Retransmission) (GOOD)
  49. Start Timer
  50. Stop ACK Timer
  51. <- 8 frame: ACK (GOOD)
  52. Stop Timer
  53. -> 12 frame: DATA (GOOD)
  54. Start Timer
  55. Stop ACK Timer
  56. <- 9 frame: DATA (GOOD) (EXPECTED)
  57. Start ACK Timer
  58. You've uploadeded the file
  59. Ack timeout 2
  60. -> 13 frame: ACK (BAD)
  61. Stop ACK Timer
  62. Timeout 5
  63. -> 14 frame: DATA (Retransmission) (GOOD)
  64. Start Timer
  65. Stop ACK Timer
  66. <- 10 frame: NAK (GOOD) (NOT BETWEEN)
  67. Timeout 6
  68. -> 15 frame: DATA (Retransmission) (GOOD)
  69. Start Timer
  70. Stop ACK Timer
  71. <- 11 frame: ACK (GOOD)
  72. Stop Timer

  73. <- 12 frame: DATA (GOOD) (NOT EXPECTED)


  74. -> 16 frame: NAK (GOOD)
  75. Stop ACK Timer
  76. <- 13 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  77. Start ACK Timer
  78. Ack timeout 3
  79. -> 17 frame: ACK (BAD)
  80. Stop ACK Timer
  81. <- 14 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  82. Start ACK Timer
  83. Ack timeout 4
  84. -> 18 frame: ACK (GOOD)
  85. Stop ACK Timer
  86. Please type in command here:

Server Output

  1. -bash-3.2$ ./Phase_4_Server
  2. <- 1 frame: DATA (BAD)


  3. -> 1 frame: NAK (GOOD)
  4. Stop ACK Timer
  5. <- 2 frame: DATA (BAD)



  6. <- 3 frame: DATA (GOOD) (EXPECTED)
  7. Start ACK Timer

  8. -> 2 frame: DATA (GOOD)
  9. Start Timer
  10. Stop ACK Timer

  11. <- 4 frame: ACK (GOOD)
  12. Stop Timer

  13. <- 5 frame: DATA (BAD)


  14. -> 3 frame: NAK (GOOD)
  15. Stop ACK Timer
  16. <- 6 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  17. Start ACK Timer
  18. Ack timeout 1
  19. -> 4 frame: ACK (GOOD)
  20. Stop ACK Timer
  21. <- 7 frame: DATA (GOOD) (EXPECTED)
  22. Start ACK Timer
  23. Ack timeout 2
  24. -> 5 frame: ACK (GOOD)
  25. Stop ACK Timer
  26. <- 8 frame: DATA (GOOD) (EXPECTED)
  27. Start ACK Timer
  28. Ack timeout 3
  29. -> 6 frame: ACK (GOOD)
  30. Stop ACK Timer
  31. <- 9 frame: DATA (BAD)


  32. -> 7 frame: NAK (GOOD)
  33. Stop ACK Timer
  34. <- 10 frame: DATA (BAD)



  35. <- 11 frame: DATA (GOOD) (EXPECTED)
  36. Start ACK Timer
  37. Ack timeout 4
  38. -> 8 frame: ACK (GOOD)
  39. Stop ACK Timer
  40. <- 12 frame: DATA (GOOD) (EXPECTED)
  41. Start ACK Timer

  42. -> 9 frame: DATA (GOOD)
  43. Start Timer
  44. Stop ACK Timer

  45. <- 13 frame: ACK (BAD)


  46. <- 14 frame: DATA (GOOD) (NOT EXPECTED)


  47. -> 10 frame: NAK (GOOD)
  48. Stop ACK Timer
  49. <- 15 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  50. Start ACK Timer
  51. Ack timeout 5
  52. -> 11 frame: ACK (GOOD)
  53. Stop ACK Timer
  54. Timeout 1
  55. -> 12 frame: DATA (Retransmission) (GOOD)
  56. Start Timer
  57. Stop ACK Timer
  58. <- 16 frame: NAK (GOOD) (NOT BETWEEN)
  59. Timeout 2
  60. -> 13 frame: DATA (Retransmission) (GOOD)
  61. Start Timer
  62. Stop ACK Timer
  63. <- 17 frame: ACK (BAD)
  64. Timeout 3
  65. -> 14 frame: DATA (Retransmission) (GOOD)
  66. Start Timer
  67. Stop ACK Timer
  68. <- 18 frame: ACK (GOOD)
  69. Stop Timer






































































































The following textbox shows the output of transmitting image.jpeg from Client to Server using the configuration below
Client ERRORRATE = 30%
Server ERRORRATE = 30%
Tick = 0.1 milisecond
Timer Interval = 50 milisecond
ACKTimer Interval = 1 milisecond

Client Output

  1. Please type in command here: UP#image.jpeg#
  2. -> 1 frame: DATA (GOOD)
  3. Start Timer
  4. Stop ACK Timer
  5. <- 1 frame: DATA (GOOD) (EXPECTED)
  6. Start ACK Timer
  7. Start uploading...
  8. Ack timeout 1
  9. -> 2 frame: ACK (BAD)
  10. Stop ACK Timer
  11. Timeout 1
  12. -> 3 frame: DATA (Retransmission) (BAD)
  13. Start Timer
  14. Stop ACK Timer
  15. <- 2 frame: NAK (GOOD) (NOT BETWEEN)
  16. Timeout 2
  17. -> 4 frame: DATA (Retransmission) (GOOD)
  18. Start Timer
  19. Stop ACK Timer
  20. <- 3 frame: ACK (GOOD)
  21. Stop Timer
  22. -> 5 frame: DATA (GOOD)
  23. Start Timer
  24. Stop ACK Timer
  25. <- 4 frame: ACK (BAD)
  26. Timeout 3
  27. -> 6 frame: DATA (Retransmission) (GOOD)
  28. Start Timer
  29. Stop ACK Timer
  30. <- 5 frame: NAK (GOOD) (NOT BETWEEN)


  31. <- 6 frame: DATA (GOOD) (NOT EXPECTED)


  32. -> 7 frame: NAK (GOOD)
  33. Stop ACK Timer
  34. Timeout 4
  35. -> 8 frame: DATA (Retransmission) (GOOD)
  36. Start Timer
  37. Stop ACK Timer
  38. <- 7 frame: ACK (GOOD)
  39. Stop Timer
  40. -> 9 frame: DATA (BAD)
  41. Start Timer
  42. Stop ACK Timer
  43. Timeout 5
  44. -> 10 frame: DATA (Retransmission) (GOOD)
  45. Start Timer
  46. Stop ACK Timer
  47. <- 8 frame: ACK (BAD)
  48. Timeout 6
  49. -> 11 frame: DATA (Retransmission) (BAD)
  50. Start Timer
  51. Stop ACK Timer
  52. <- 9 frame: NAK (GOOD) (NOT BETWEEN)
  53. Timeout 7
  54. -> 12 frame: DATA (Retransmission) (GOOD)
  55. Start Timer
  56. Stop ACK Timer
  57. <- 10 frame: ACK (BAD)


  58. <- 11 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  59. Start ACK Timer
  60. Ack timeout 2
  61. -> 13 frame: ACK (BAD)
  62. Stop ACK Timer
  63. Timeout 8
  64. -> 14 frame: DATA (Retransmission) (BAD)
  65. Start Timer
  66. Stop ACK Timer
  67. Timeout 9
  68. -> 15 frame: DATA (Retransmission) (GOOD)
  69. Start Timer
  70. Stop ACK Timer
  71. <- 12 frame: ACK (GOOD)
  72. Stop Timer
  73. -> 16 frame: DATA (GOOD)
  74. Start Timer
  75. Stop ACK Timer
  76. <- 13 frame: ACK (GOOD)
  77. Stop Timer
  78. -> 17 frame: DATA (GOOD)
  79. Start Timer
  80. Stop ACK Timer
  81. <- 14 frame: ACK (BAD)
  82. Timeout 10
  83. -> 18 frame: DATA (Retransmission) (GOOD)
  84. Start Timer
  85. Stop ACK Timer
  86. <- 15 frame: NAK (BAD)
  87. Timeout 11
  88. -> 19 frame: DATA (Retransmission) (BAD)
  89. Start Timer
  90. Stop ACK Timer
  91. <- 16 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  92. Start ACK Timer
  93. Ack timeout 3
  94. -> 20 frame: ACK (GOOD)
  95. Stop ACK Timer
  96. <- 17 frame: DATA (GOOD) (EXPECTED)
  97. Start ACK Timer
  98. You've uploadeded the file
  99. Ack timeout 4
  100. -> 21 frame: ACK (GOOD)
  101. Stop ACK Timer
  102. Timeout 12
  103. -> 22 frame: DATA (Retransmission) (GOOD)
  104. Start Timer
  105. Stop ACK Timer
  106. <- 18 frame: ACK (GOOD)
  107. Stop Timer
  108. Please type in command here:

Server Output

  1. -bash-3.2$ ./Phase_4_Server
  2. <- 1 frame: DATA (GOOD) (EXPECTED)
  3. Start ACK Timer

  4. -> 1 frame: DATA (GOOD)
  5. Start Timer
  6. Stop ACK Timer
  7. <- 2 frame: ACK (BAD)



  8. <- 3 frame: DATA (BAD)


  9. -> 2 frame: NAK (GOOD)
  10. Stop ACK Timer
  11. <- 4 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  12. Start ACK Timer
  13. Ack timeout 1
  14. -> 3 frame: ACK (GOOD)
  15. Stop ACK Timer
  16. <- 5 frame: DATA (GOOD) (EXPECTED)
  17. Start ACK Timer
  18. Ack timeout 2
  19. -> 4 frame: ACK (BAD)
  20. Stop ACK Timer
  21. <- 6 frame: DATA (GOOD) (NOT EXPECTED)


  22. -> 5 frame: NAK (GOOD)
  23. Stop ACK Timer
  24. Timeout 1
  25. -> 6 frame: DATA (Retransmission) (GOOD)
  26. Start Timer
  27. Stop ACK Timer
  28. <- 7 frame: NAK (GOOD) (NOT BETWEEN)


  29. <- 8 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  30. Start ACK Timer
  31. Ack timeout 3
  32. -> 7 frame: ACK (GOOD)
  33. Stop ACK Timer
  34. <- 9 frame: DATA (BAD)



  35. <- 10 frame: DATA (GOOD) (EXPECTED)
  36. Start ACK Timer
  37. Ack timeout 4
  38. -> 8 frame: ACK (BAD)
  39. Stop ACK Timer
  40. <- 11 frame: DATA (BAD)


  41. -> 9 frame: NAK (GOOD)
  42. Stop ACK Timer
  43. <- 12 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  44. Start ACK Timer
  45. Ack timeout 5
  46. -> 10 frame: ACK (BAD)
  47. Stop ACK Timer
  48. Timeout 2
  49. -> 11 frame: DATA (Retransmission) (GOOD)
  50. Start Timer
  51. Stop ACK Timer
  52. <- 13 frame: ACK (BAD)


  53. <- 14 frame: DATA (BAD)



  54. <- 15 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  55. Start ACK Timer
  56. Ack timeout 6
  57. -> 12 frame: ACK (GOOD)
  58. Stop ACK Timer
  59. <- 16 frame: DATA (GOOD) (EXPECTED)
  60. Start ACK Timer
  61. Ack timeout 7
  62. -> 13 frame: ACK (GOOD)
  63. Stop ACK Timer
  64. <- 17 frame: DATA (GOOD) (EXPECTED)
  65. Start ACK Timer
  66. Ack timeout 8
  67. -> 14 frame: ACK (BAD)
  68. Stop ACK Timer
  69. <- 18 frame: DATA (GOOD) (NOT EXPECTED)


  70. -> 15 frame: NAK (BAD)
  71. Stop ACK Timer
  72. <- 19 frame: DATA (BAD)
  73. Timeout 3

  74. -> 16 frame: DATA (Retransmission) (GOOD)
  75. Start Timer
  76. Stop ACK Timer
  77. <- 20 frame: ACK (GOOD)
  78. Stop Timer
  79. -> 17 frame: DATA (GOOD)
  80. Start Timer
  81. Stop ACK Timer

  82. <- 21 frame: ACK (GOOD)
  83. Stop Timer

  84. <- 22 frame: DATA (GOOD) (NOT EXPECTED) (NAK EXISTS)
  85. Start ACK Timer
  86. Ack timeout 9
  87. -> 18 frame: ACK (GOOD)
  88. Stop ACK Timer











































































































































=========================================== Step 6 ==============================================
If you've made this far, you then have a well-built error-tolerant client/server program that is based on selective repeat protocol. You can play around by specifying different combinations of error rate at client side and server side. You can also change the length of a tick, the retransmission timer interval and ACK timer interval to see what the results are. 
The goal we need to aim next is to increase the windows size. Implementing a sliding window of only one buffer obviously does not make full use of selective repeat protocol. At this step, let's not aim too big, making the windows size from 1 to 2 is enough. 
There is nothing much left to talk about extending the window size, what you need to do is to set the NR_BUFS to 2, thus the number of all the timers, buffers are doubled. There is still one tiny trivial thing you need to implement before finishing Step 6. That is to solve the problem of determining which frame caused a timeout. There is plenty of workaround for this problem. What I ended up doing is to add an array oldest_frame_seq storing the frame sequence number of the packet stored at buffer out_buf in Datalink Layer. Thus whenever a timer times out, we look up the frame sequence number stored in the same index of the array oldest_frame_seq and resend that frame to receiver. (Please refer to the last two paragraphs at page 228 in the textbook). 

========================================= Step 7 ============================================
In Step 7, let's double the window size to make it 4. It's very easy to do it, just change NR_BUFS to 4 and add two more timers in Timer Process. However, things turned out to be not as smooth as I expected. The transmission stopped at certain point when I tried to send image.jpg to server. Looking into the log file (which I have added at Step 6), I found out that the variable nbuffered which is used to track the usage of outgoing buffer reaches 5 after certain point during transmission, which should not be allowed. This bug is caused by DLL asking APP to send packet to it too frequently. If you take a look at the end of the  while loop inside DLL, you'll find 
if(nbuffered<NR_BUFS)
enable_app_layer();
is executed in each iteration, while the case app_layer_ready is not executed in each iteration. Thus nbuffered is not incremented in time to to reflect the effect of enabling application layer. The workaround is to keep a nbuffered at Application Layer, which is kept updated synced with the nbuffered at Datalink Layer. You can easily achieve this by using select() function based on the structure we've built so far. 

========================================= Step 8 =============================================
Just in case there are any other bugs that are not exposed yet and to make sure the our code is robust enough, I added Step 8 to increase the window size to 8. Then transmit the sample files. It turned out the programs are working pretty well!!

======================================== Conclusion ==========================================
Now I can finally announce that we've successfully implement Selective Repeat Protocol. It is a big piece of work, which involves socket programming, multi-process programming and massive use of select method. The essential of Multi-process programming is to let the processes be aware of the current state of each other and behaves correspondingly. Thus, socket programming is, to some extent, a kind of multi-process programming, because client and server try to notify each other the current state of themselves.

No comments:

Post a Comment