TCP 首部有哪些关键字段?它们分别解决什么问题?
TCP 首部不是一串要死记的字段,而是 TCP 可靠传输的控制面板。端口决定数据交给哪个进程,序列号和确认号让字节流不乱,标志位表达连接状态,窗口、校验和、选项分别处理流量控制、差错检测和能力协商。最小首部 20 字节,带选项最多 60 字节;抓包时真正有用的不是背出字段名,而是看这些字段是否在按预期变化。
TCP 首部整体长什么样?
文字图示可以这样记:源端口和目的端口各 16 位,后面是 32 位序列号、32 位确认号,再往后是数据偏移、保留位、控制标志、窗口大小、校验和、紧急指针,最后才是可变长选项和数据。数据偏移说明首部在哪里结束,因为 MSS、窗口扩大、时间戳、SACK 等选项会改变首部长度。
哪些字段负责定位和可靠性?
源端口、目的端口配合源 IP、目的 IP,组成一条连接的四元组。IP 只能送到主机,TCP 还要把数据送到具体应用,例如浏览器临时端口连到服务器 443 端口。NAT、代理、容器网络可能改写端口,所以抓包端口不一定等于应用配置端口。
序列号表示本段第一个数据字节的位置,确认号表示“下一步希望收到哪个字节”。ack=1001 通常代表 1001 之前都收到了,这是累积确认。SYN 和 FIN 也各占一个序列号,手算握手、挥手时这里最容易错。
标志位、窗口和选项怎么影响排查?
SYN 用于建立连接,ACK 表示确认号有效,FIN 是正常关闭,RST 更像异常中止。PSH 不等于强制立刻发送,URG 在现代应用里很少依赖。看到连接断开时,先区分 FIN 还是 RST,前者多是正常收尾,后者常见于端口未监听、应用拒绝或中间设备清理状态。
窗口大小告诉对端还能接收多少数据,是流量控制的核心。原始窗口只有 16 位,高带宽高延迟链路通常要靠窗口扩大选项。校验和能发现传输损坏,但不是安全机制;MSS、SACK、时间戳这些选项,则会影响分段大小、丢包恢复和 RTT 估算。
追问
为什么 TCP 首部最小 20 字节、最大 60 字节?
数据偏移字段只有 4 位,单位是 32 位字。最小值通常是 5,也就是 20 字节;最大值是 15,也就是 60 字节。边界在于 TCP 选项最多只有 40 字节,MSS、SACK、时间戳、窗口扩大都要在这里取舍。
序列号为什么按字节编号,而不是按报文编号?
TCP 给应用层的是连续字节流,不保留消息边界。按字节编号后,拆包、合包、乱序到达都能重新拼回正确顺序。代价是应用如果需要消息边界,必须自己加长度字段或分隔符,很多“粘包”问题就踩在这里。
窗口大小是不是越大越好?
不是,窗口太小会限制吞吐,窗口太大也可能让数据在接收端或链路上堆积。流量控制看接收缓冲区,拥塞控制看网络承载能力,两者不能混为一谈。调优要结合 RTT、带宽、丢包率和应用消费速度,而不是盲目把窗口调大。
抓包时先看哪些字段最有用?
建连先看 SYN、SYN+ACK、ACK,以及 MSS、SACK、窗口扩大是否协商成功。传输异常看 seq、ack、窗口、重复 ACK、重传和 RST。常见踩坑是只看服务端日志,以为服务慢;抓包才发现接收窗口归零,瓶颈其实在客户端消费太慢。