# Lab 2: Go-Back-N RDT
## 實驗場景
* 由sender端傳data到receiver,接著receiver會回應ACKs
* Receiver端運行go-back-n,並會檢查是否收到所有data
* Python 3.8.10

## Sender端設定
send_base = 0 --> send_base指標位置
next_seq_num = 0 --> next_seq_num位置
cwnd_size = 3 --> window的大小為3
num_pkt = 10 --> 總共要送出10個封包
## Sender端需完成功能
* Send_base及next_seq_num要在正確的位置
* Window內的data需接連送出
* 設定timer的時間為5秒
* Timeout時需要重傳window內所有的data
* Sender結束前需送出10筆資料
本次lab需完成下方sender端程式
```python=
import socket
import time
HOST = '127.0.0.1'
PORT = 8000
server_addr = (HOST, PORT)
send_base = 0
next_seq_num = 0
cwnd_size = 3
num_pkt = 10
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# TODO: write your codes here
```
[程式碼下載](https://drive.google.com/file/d/10D-vUTa1uW3j8MBgW9lZbsEpOQqMXOCH/view?usp=sharing)
封包中需傳送sequence number如下:
```
clientMessage = str(next_seq_num)
client.sendto(clientMessage.encode(), server_addr)
```
## 設定timer
以下為設定timer的sample codes
程式碼如下:
```python=
client.settimeout(5)
try:
serverMessage, addr = client.recvfrom(1024)
except Exception as e:
print('timeout')
# the codes to handle the timeout event
```
在這個sample codes,我們使用settimeout去設定timeout的時間,單位是秒。其中client是一個socket,而settimeout是socket的一個member function。在沒有設定timeout時間的情況下,recvfrom會一直等待直到收到資料才會return。若有設定timeout時間,在時間內沒有收到資料,會出現exception。接著程式會跳到except這個label的section開始執行。因此我們可以在這個section中去處理timeout事件,例如啟動重傳的機制。
## Receiver端測試程式
```python=
# -*- coding: utf-8 -*-
import socket
import numpy as np
HOST = '127.0.0.1'
PORT = 8000
expected = 0
num_pkt = 10
pkt_loss = np.zeros((num_pkt, 1))
pkt_loss[2] = 1
pkt_loss[9] = 1
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind((HOST, PORT))
while True:
clientMessage, addr = server.recvfrom(1024)
print('Client message is:', clientMessage.decode("utf-8"))
seq = int(clientMessage)
if(pkt_loss[seq] == 1):
pkt_loss[seq] = 0
seq = -1
if seq == expected:
server.sendto(clientMessage, addr)
expected = expected + 1
elif seq == -1:
print('pakcet loss')
else:
print('bad packet')
clientMessage = str(expected - 1)
server.sendto(clientMessage.encode(), addr)
if expected == num_pkt:
print('Have received all packets')
break
```
[程式碼下載](https://drive.google.com/file/d/1zi2JYYBxCctdpWGdkQrxORMJeAn53uhM/view?usp=sharing)
在測試的接收端程式中,會利用pkt_loss這個array來記錄那些封包是遺失的。每當收到封包時,接收端會去檢查封包的sequence number(放在封包的payload裡面)。如果sequence number是預期的,則會回應此sequence number給發送端,做為ack number。若這個封包為遺失(看對應的pkt_loss是否為1),則不會發出任何封包做為ack。若封包沒有遺失,但是sequence number不是預期的,則會再回應前一次送出的ack number (expected -1)。