TCP のシーケンス番号と ACK 番号の増え方

# まとめ
-  受信したシーケンス番号に + (受信データ長) したものを ACK 番号に入れて返す
-  受信した ACK 番号を次のシーケンス番号とする

# 実験
nc と tcpdump を使って、シーケンス番号と ACK 番号の増え方を観察してみます。

## サーバ側
nc -l \<port> で、指定したポートで接続を待ちます。

```
$ nc -l 50000
```

## クライアント側
### tcpdump 
-i でキャプチャするインターフェースを指定し、-w でファイルに出力します。

```
$ tcpdump -i wlp2s0 -w dump.pcap
```

### nc
nc をクライアントとして用いる場合、nc \<IP\> \<port\> でサーバの IP と port を指定します。

```
$ nc 192.168.179.6 50000
```

### データ送信
クライアント側で適当に何か入力してデータを送信し、その後接続を切ります。

```
$ nc 192.168.179.6 50000
hello
hogehoge
^C
$
```

サーバに送ったデータが表示され、接続が切れていました。

```
$ nc -l 50000
hello
hogehoge
$
```

### tcpdump 結果
キャプチャ停止後に、-r コマンドでキャプチャしたファイルを読み込みます。-S でシーケンス番号を絶対番号で表示し、 port 50000 により、50000 番ポートの通信のみを抽出します。

```
$ tcpdump -r dump.pcap -S port 50000
reading from file dump.pcap, link-type EN10MB (Ethernet)
22:44:27.574365 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [S], seq 3931966036, win 29200, options [mss 1460,sackOK,TS val 4212938433 ecr 0,nop,wscale 7], length 0
22:44:27.579376 IP 192.168.179.6.50000 > 192.168.179.5.48882: Flags [S.], seq 792281538, ack 3931966037, win 28960, options [mss 1460,sackOK,TS val 1020480106 ecr 4212938433,nop,wscale 7], length 0
22:44:27.579462 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [.], ack 792281539, win 229, options [nop,nop,TS val 4212938435 ecr 1020480106], length 0
22:44:29.079095 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [P.], seq 3931966037:3931966043, ack 792281539, win 229, options [nop,nop,TS val 4212938809 ecr 1020480106], length 6
22:44:29.092398 IP 192.168.179.6.50000 > 192.168.179.5.48882: Flags [.], ack 3931966043, win 227, options [nop,nop,TS val 1020480484 ecr 4212938809], length 0
22:44:45.468223 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [P.], seq 3931966043:3931966052, ack 792281539, win 229, options [nop,nop,TS val 4212942907 ecr 1020480484], length 9
22:44:45.524994 IP 192.168.179.6.50000 > 192.168.179.5.48882: Flags [.], ack 3931966052, win 227, options [nop,nop,TS val 1020484579 ecr 4212942907], length 0
22:44:46.858640 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [F.], seq 3931966052, ack 792281539, win 229, options [nop,nop,TS val 4212943254 ecr 1020484579], length 0
22:44:46.866443 IP 192.168.179.6.50000 > 192.168.179.5.48882: Flags [F.], seq 792281539, ack 3931966053, win 227, options [nop,nop,TS val 1020484927 ecr 4212943254], length 0
22:44:46.866553 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [.], ack 792281540, win 229, options [nop,nop,TS val 4212943256 ecr 1020484927], length 0
```

## 解析
### 3-way handshake
クライアント側のポートは 48882 のよう。Flags の [S] が SYN, [.] が ACK です。
はじめの 3 行で SYN -> SYN/ACK -> ACK の 3-way handshake が見えます。

```
22:44:27.574365 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [S], seq 3931966036, win 29200, options [mss 1460,sackOK,TS val 4212938433 ecr 0,nop,wscale 7], length 0
22:44:27.579376 IP 192.168.179.6.50000 > 192.168.179.5.48882: Flags [S.], seq 792281538, ack 3931966037, win 28960, options [mss 1460,sackOK,TS val 1020480106 ecr 4212938433,nop,wscale 7], length 0
22:44:27.579462 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [.], ack 792281539, win 229, options [nop,nop,TS val 4212938435 ecr 1020480106], length 0
```

これから、

-  受信したシーケンス番号に + 1 したものを ACK 番号に入れて返す
-  受信した ACK 番号が次のシーケンス番号になる

ことが分かります。

|                |flag   | seq      | ack                       |
|:---------------|:------|---------:|--------------------------:|
|Client -> Server|SYN    |3931966036|0                          |
|Server -> Client|SYN/ACK|792281538 |3931966037 (3931966036 + 1)|
|Client -> Server|ACK    |3931966037|792281539 (792281538 + 1)  |

### データ送信
以下 4 行が "hello" と "hogehoge" を送信した際のキャプチャ。

```
22:44:29.079095 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [P.], seq 3931966037:3931966043, ack 792281539, win 229, options [nop,nop,TS val 4212938809 ecr 1020480106], length 6
22:44:29.092398 IP 192.168.179.6.50000 > 192.168.179.5.48882: Flags [.], ack 3931966043, win 227, options [nop,nop,TS val 1020480484 ecr 4212938809], length 0
22:44:45.468223 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [P.], seq 3931966043:3931966052, ack 792281539, win 229, options [nop,nop,TS val 4212942907 ecr 1020480484], length 9
22:44:45.524994 IP 192.168.179.6.50000 > 192.168.179.5.48882: Flags [.], ack 3931966052, win 227, options [nop,nop,TS val 1020484579 ecr 4212942907], length 0
```
これより、

-  受信したシーケンス番号に + (受信データ長) したものを ACK 番号に入れて返す
-  受信した ACK 番号が次のシーケンス番号になる

ことが分かります。

|                |flag     | seq      | ack      |
|:---------------|:--------|---------:|---------:|
|Client -> Server|PUSH/ACK |3931966037|792281539 |
|Server -> Client|ACK      |792281539 |3931966043 (3931966037 + 6)|
|Client -> Server|PUSH/ACK |3931966043|792281539 |
|Client -> Server|ACK      |792281539 |3931966052 (3931966043 + 9)|

### コネクション切断
FIN -> FIN/ACK -> ACK の流れで、受信したシーケンス番号 + 1 が ACK 番号となるのは接続開始時と同様です。

```
22:44:46.858640 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [F.], seq 3931966052, ack 792281539, win 229, options [nop,nop,TS val 4212943254 ecr 1020484579], length 0
22:44:46.866443 IP 192.168.179.6.50000 > 192.168.179.5.48882: Flags [F.], seq 792281539, ack 3931966053, win 227, options [nop,nop,TS val 1020484927 ecr 4212943254], length 0
22:44:46.866553 IP 192.168.179.5.48882 > 192.168.179.6.50000: Flags [.], ack 792281540, win 229, options [nop,nop,TS val 4212943256 ecr 1020484927], length 0
```