1. TCP协议基础:协议栈位置、报文格式、端口号与UDP对比

各位好,我是老张。做网络抓包分析十几年了,每次带新人,我都是从TCP协议栈讲起。为什么?因为你不搞清楚TCP在协议栈里到底站在哪个位置,后面看三次握手、重传、窗口滑动这些概念,很容易一头雾水。

说白了,TCP就是网络世界里那个最靠谱的快递员。它不追求最快,但保证你寄出去的东西,对方一定能收到,而且顺序不乱。今天这一章,我们先打好地基。

1.1 TCP在协议栈中的位置

TCP/IP协议栈分四层,从上到下依次是:应用层、传输层、网络层、网络接口层。TCP就住在传输层,跟UDP是邻居。

我习惯用一张图来理解这个层次关系,你看下面这张SVG图,一目了然。

TCP/IP协议栈四层模型 应用层 HTTP / FTP / SMTP / SSH / DNS 传输层 TCP(可靠、面向连接) UDP(不可靠、无连接) 网络层 IP / ICMP / ARP / RARP 网络接口层 以太网 / WiFi / 物理介质 TCP位于传输层,负责端到端的可靠数据传输 上层应用数据经过TCP封装后,交给IP层进行路由转发

你看,应用层的数据比如HTTP请求,先交给传输层的TCP。TCP给它加上头部,变成TCP报文段。然后交给网络层的IP,IP再加个头部,变成IP数据包。最后通过网络接口层发出去。

反过来,收到数据时,每一层都会剥掉自己的头部,把数据往上递。这就是所谓的"分层解耦"。

小提示: 在Wireshark里抓包时,你会看到每一层的头部信息。比如一个HTTP请求包,Wireshark会展示:Frame(物理帧)→ Ethernet II(以太网)→ IP(网络层)→ TCP(传输层)→ HTTP(应用层)。一层一层剥开,跟洋葱似的。

1.2 TCP报文格式

TCP报文格式,是抓包分析的核心。你如果看不懂TCP头部,那Wireshark里的那些字段对你来说就是天书。我当年刚学的时候,硬是把这张表背下来了。

TCP头部最少20字节,最多60字节。下面这张表列出了关键字段:

字段 长度(位) 说明
源端口号 16 发送方的端口,范围0-65535
目的端口号 16 接收方的端口
序列号(SEQ) 32 本报文段数据的第一个字节的序号
确认号(ACK) 32 期望收到的下一个字节的序号
数据偏移 4 TCP头部长度,单位是4字节
标志位 9 SYN、ACK、FIN、RST等控制位
窗口大小 16 接收方还能接收的数据量,用于流量控制
校验和 16 校验头部+数据的完整性
紧急指针 16 URG标志位为1时有效

这里我重点说一下几个关键字段:

  • 序列号和确认号:这是TCP可靠传输的基石。序列号标记了数据流中每个字节的位置,确认号告诉对方"我收到哪了,你接着发哪"。三次握手时,这两个字段的变化是核心。
  • 标志位:SYN用于建立连接,ACK用于确认,FIN用于关闭连接,RST用于异常复位。我在项目中遇到过好几次,服务器突然发RST包,客户端直接断开连接。后来一查,是后端服务挂了。
  • 窗口大小:这个字段决定了发送方能发多少数据而不等确认。窗口越大,吞吐量越高。但窗口太大也可能导致接收方缓冲区溢出。
重点记忆: 三次握手中,第一次握手是SYN=1, SEQ=x;第二次握手是SYN=1, ACK=1, SEQ=y, ACK=x+1;第三次握手是ACK=1, SEQ=x+1, ACK=y+1。这个序列号+1的逻辑,是理解TCP连接建立的关键。

1.3 TCP端口号

端口号,说白了就是一台机器上不同应用程序的"门牌号"。IP地址找到了这台机器,端口号找到了机器上的具体进程。

端口号范围是0到65535,分为三类:

  • 知名端口(0-1023):系统保留,给常见服务用。比如HTTP用80,HTTPS用443,FTP用21,SSH用22。
  • 注册端口(1024-49151):给用户进程或应用程序使用。比如MySQL用3306,Tomcat用8080。
  • 动态/私有端口(49152-65535):客户端临时使用。你打开浏览器访问一个网站,系统会随机分配一个这个范围内的端口作为源端口。

我记得有一次排查一个连接问题,发现客户端一直连不上服务器的8080端口。我抓包一看,服务器根本没在8080上监听。后来发现运维把服务端口改成了8081,但没通知我们。你看,端口号搞错了,连接就建立不起来。

避坑指南: 我曾经遇到过一个问题——客户端访问服务器,Wireshark里看到SYN包发出去了,但服务器没回SYN+ACK。排查了半天,发现是服务器防火墙把目标端口给封了。所以,当你看到"SYN_SENT"状态但收不到响应时,先检查防火墙和端口是否开放。

1.4 TCP与UDP对比

TCP和UDP,一个像顺丰快递(保价、签收、可追踪),一个像扔纸飞机(扔出去就不管了)。两者各有各的适用场景。

下面这张表,是我做培训时必讲的对比:

对比项 TCP UDP
连接性 面向连接,需三次握手 无连接,直接发数据
可靠性 可靠传输,有确认、重传机制 不可靠,不保证送达
有序性 保证数据按序到达 不保证顺序
流量控制 有滑动窗口机制 无
拥塞控制 有慢启动、拥塞避免等 无
头部开销 20-60字节 8字节
传输效率 较低 较高
典型应用 HTTP、FTP、SMTP、SSH DNS、DHCP、视频直播、VoIP

你想想看,为什么视频直播用UDP而不是TCP?因为直播可以容忍偶尔丢几帧画面,但不能容忍卡顿。TCP一旦丢包就重传,重传导致延迟,画面就卡住了。UDP丢包就丢了,画面花一下,但流畅度保住了。

反过来,为什么网页浏览用TCP?因为网页内容必须完整、有序地到达。你打开一个网页,HTML、CSS、JS文件一个都不能少,顺序也不能乱。TCP的可靠性在这里就是刚需。

个人经验: 我在做VoIP(网络电话)优化时,曾经尝试过用TCP传输语音数据。结果呢?网络一丢包,TCP就开始重传,语音延迟飙升,通话质量惨不忍睹。后来换成UDP+RTP,配合前向纠错(FEC),效果好了很多。所以,选TCP还是UDP,核心就看你的业务能不能容忍丢包。

1.5 本章小结

这一章我们讲了TCP的基础知识。总结下来就三句话:

  • TCP在传输层,负责端到端的可靠数据传输。
  • TCP头部20字节,序列号、确认号、标志位、窗口大小是关键字段。
  • TCP面向连接、可靠有序;UDP无连接、高效但不可靠。选哪个,看业务场景。