---
# System prepended metadata

title: 'Lab 2: Go-Back-N RDT'

---

# Lab 2: Go-Back-N RDT

## 實驗場景

* 由sender端傳data到receiver，接著receiver會回應ACKs
* Receiver端運行go-back-n，並會檢查是否收到所有data
* Python 3.8.10

![](https://i.imgur.com/bYTs1sz.png)

## 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)。
