端口号确定后,数据还缺少一个关键问题:用什么方式传。TCP/IP 协议族中,传输层最重要的两个协议是 TCP(传输控制协议) 和 UDP(用户数据报协议)。
不同应用往往需要不同取舍:下载文件、打开网页时,一个字节的错误或丢失都可能造成文件损坏、页面错乱,因此需要可靠传输;而在线语音、实时游戏等场景,如果某个语音包丢了,几秒后再重传已经没有意义,此时低延迟比绝对可靠更重要,因此更适合轻量传输。
TCP:三次握手建立可靠连接
TCP 是一种面向连接、可靠、基于字节流的传输协议。双方正式发送业务数据之前,会先通过“三次握手”确认彼此可以正常收发包,并协商初始序列号。
- 第一次握手(SYN):客户端向服务器发送
SYN=1的报文段,并随机选择一个初始序列号seq=100,表示:“我想和你建立连接,我这边数据的起始编号是 100。” - 第二次握手(SYN-ACK):服务器收到后回复
SYN=1, ACK=1。服务器随机选择自己的初始序列号seq=700,并设置确认号ack=101,表示:“我收到了你的请求,也同意建立连接;我这边数据从 700 开始,并且期待你的下一个字节编号是 101。” - 第三次握手(ACK):客户端收到后回复
ACK=1,并设置ack=701,表示:“我也收到了你的确认,连接可以建立。”
三次握手完成后,双方会在内核中分配连接资源,TCP 连接进入 ESTABLISHED 状态。之后,应用程序就可以通过这条连接传输数据。
序列号与确认号:TCP 如何保证不丢包
TCP 并不是简单地把数据发出去就结束,它会给每个字节编号。发送端把应用数据拆成多个 TCP 报文段,每个字节都有对应的序列号(Sequence Number),接收端通过确认号(Acknowledgment Number)告诉发送端:“我已经收到哪里了,接下来请从哪里开始发。”
例如,发送端连续发出序列号 401 到 406 的 6 个字节。接收端完整收到后,会回复一个 ACK 报文,确认号设置为 ack=407。
ack=407 的含义是:407 之前的字节我已经连续、完整地收到了,请从第 407 个字节开始发给我。
如果中途有数据包丢失:
接收端已连续收到: 字节 101 ~ 105
中途意外丢失: 字节 106 ~ 110(缺口!)
后续抢先到达: 字节 111 ~ 115
接收端虽然收到了 111~115,但中间缺少 106~110,所以确认号不能跳到 116,只能继续回复 ack=106。这种机制称为累积确认。收到但未交付给应用的乱序数据会先放入缓冲区,等待缺失部分补齐。
如果发送端长时间收不到 ack=106,就会判断该段数据可能丢失,并自动重传 106~110。只有缺口补齐后,接收端才会把完整数据按顺序交给上层应用。

