在网络编程中,我们经常直接调用send()和recv(),却很少关注底层发生了什么。其实,传输层协议(TCP)为了保证数据的可靠性,在后台做了大量复杂的工作:从建立连接时的“三次握手”,到通信过程中的“滑动窗口”流量控制。
本文将结合课堂笔记,带你拆解 TCP 协议头结构,并通过代码实战观察 TCP 通信流程。
一、 TCP 协议头:数据的“护照”
每一个 TCP 数据块(Segment)都包含一个复杂的首部。根据笔记,关键字段如下:
- 端口号(Source/Dest Port):各占 2 字节,决定数据交给哪个进程。
- 序号(Sequence Number):32位随机数,用于解决网络包乱序问题。
- 确认序号(Acknowledgment Number):即小写的
ack,告诉对方下一次该从哪个字节开始发。 - 标志位:如大写的
ACK(确认)、SYN(同步)、FIN(终止)。 - 窗口大小(Window Size):16位,这是滑动窗口机制的核心,表示接收端还能收多少数据。
- 校验和(Checksum):用于检测数据在传输中是否损坏,UDP 也极度依赖此项。
二、 连接的生命周期:三次握手与四次挥手
1. 三次握手(建立连接)
- 服务器端:调用
listen()进入监听状态。 - 客户端:调用
connect()发起连接。 - 过程:客户端发送 SYN,服务端回传 SYN+ACK,客户端再回 ACK。当
connect()返回成功时,三次握手即告完成。
2. 四次挥手(断开连接)
这是连接释放的过程,确保双方都已停止发送并关闭缓冲区。
三、 滑动窗口:自动化的流量控制
滑动窗口是 TCP 最精妙的设计之一。
- 位置:它存在于 TCP 协议头中,而不是应用层(如 HTTP 头)。
- 透明性:开发者只需关注应用层数据(如 “hello”),传输层会自动封装窗口大小信息。
- 作用:如果接收方处理慢,窗口会变小;处理快,窗口变大。这避免了发送方速度过快导致接收方缓冲区溢出。
四、 代码实战:Socket 通信流程演示
在 Python 中,当我们指定type=socket.SOCK_STREAM时,系统就默认启用了 TCP 协议。
1. 服务端代码 (tcp_server.py)
服务端通过listen()启动监听,等待三次握手。
importsocketdefstart_server():# 1. 创建 Socket (SOCK_STREAM 表示使用 TCP)server_sock=socket.socket