1. 示例实现过程
  2. TCP 数据格式
  3. TCP 标志
  4. Sequnence Number 序号
  5. Acknowledgment Number 确认序号
  6. 建立TCP连接(三次握手)
  7. 终止TCP连接(四次挥手)
  8. 为什么 SYN 和 FIN 的响应 ACK 要 + 1 ?
  9. 为什么终止TCP连接需要四次?
  10. 位和字节

TCP 建立连接与终止连接的过程

示例实现过程

1 使用 http-server 创建一个临时的服务器, 链接为 http://127.0.0.1:8080
2 打开 WireShark, 在过滤器中输入如下命令,来过滤出我们所需的包.这条命令表示过滤出 source(来源) 地址或 destination(目的地) 地址为 127.0.0.1:8080 的包.

1
ip.src==127.0.0.1:8080 or ip.dst==127.0.0.1:8080  

3 使用任意浏览器窗口访问 http://127.0.0.1:8080 即可.注意等待一段时间后需要关闭窗口,否则可能抓取不到终止TCP连接时的 四次挥手.

下图为一个完整的 TCP 通信流程, 通过 Wireshark 抓包获取.
4c9b0180.png

Wireshark 第三格的数据格式默认为 16 进制, 可通过点击鼠标右键 -> as bits 切换为 2 进制格式
3651236f.png

TCP 数据格式

下图是 TCP 数据格式, TCP 部首的大小通常为 20 个字节(20 * 8 = 160 位)(如果不包括 选项 的话)

屏幕截图 2022-03-26 193620.png

下图是 Wireshark 抓取的 TCP 部首

屏幕截图 2022-03-22 202538.png

TCP 标志

1 URG 紧急指针
2 ACK 确认应答
3 PSH 发送数据
4 RST 重置请求
5 SYN 建立连接,握手时发送
6 FIN 终止连接,挥手时发送

Sequnence Number 序号

初始的 Sequence Number 被称为 ISN(Initial Sequence Number),是一个随机数.
之后的 Sequence Number = 上次发送的 Sequence Number + 上次发送的 TCP payload

Sequnence Number 的作用是判断接收方是否成功收到了数据.
当接收方收到数据时, 返回 ACK 携带 Acknowledgment Number(= Sequnence Number + TCP payload (数据大小)). 发送方通过收到的 Acknowledgment Number 来判断是否发送成功.

以下图客户端的 HTTP 请求为例:
此次的 Sequence Number 为 2873872653
屏幕截图 2022-03-22 232238.png

整个数据包大小为 893 字节, Null/Loopback(?) + IP 部首 + TCP 部首(4 + 20 + 20) 为 44 字节.
HTTP 数据为 849 (893 - 44)字节

Null/Loopback:
屏幕截图 2022-03-22 231655.png

ip部首:
79b950a0.png

TCP 部首:
0a623e83.png

客户端下一次发送的 Sequence Number = 2873873502 (2873872653 + 849)
屏幕截图 2022-03-22 232607.png

Acknowledgment Number 确认序号

Acknowledgment Number = 上一次收到的 Sequence Number + 上一次收到的 TCP payload
注意 SYN 和 FIN 也占一个序号,因此 SYN 和 FIN 的 ACK 会 +1

以下图的HTTP请求为例, 客户端向服务器请求根目录下的资源, 发送了如下数据:
Sequence Number 为 2873872653, TCP payload 为 849.
屏幕截图 2022-03-22 235832.png
再看看下图服务器的响应,服务器返回 Acknowledgment Number 为 2873873502, 减去 TCP payload 849 正好等于 2873872653

屏幕截图 2022-03-22 235634.png

建立TCP连接(三次握手)

握手过程:
1 客户端发送: SYN=1 SequenceNumber=2873872652
2 服务器收到消息(1),向客户端发送: SYN=1 ACK=1 SequneceNumber=3105526224 AcknowledgmentNumber=2873872653
3 客户端收到消息(2),向服务器发送: ACK=1 SequenceNumber=2873872653 AcknowledgmentNumber=3105526225

终止TCP连接(四次挥手)

挥手过程:
1 服务器发送: FIN=1 ACK=1 SequenceNumber=3105526493 AcknowledgmentNumber=2873873502
2 客户端收到消息(1),向服务器发送 ACK=1 SequenceNumber=2873873502 AcknowledgmentNumber=3105526494
3 客户端发送: FIN=1 ACK=1 SequenceNumber=2873873502 AcknowledgmentNumber=3105526494
4 服务器收到消息(2),向客户端发送 ACK=1 SequenceNumber=3105526494 AcknowledgmentNumber=2873873503

注意: 通信的双方皆可发起FIN来终止TCP连接(一般由客户端发起)

为什么 SYN 和 FIN 的响应 ACK 要 + 1 ?

因为TCP 协议规定, SYN 和 FIN 占用一个序号.

为什么终止TCP连接需要四次?

TCP是全双工协议,通信双方都可以发送数据.
当某一方收到带有FIN标志的消息时,可能还有未发完的数据.此时不能将 ACK 和 FIN 合并.

位和字节

  • 位 bit: 计算机的最小单位, 1 bit 只能储存 0 或 1
  • 字节 byte: 1 byte = 8 bit
  • 1KB = 1024 byte (2^10)