文章目录
- 一、TCP/IP协议栈整体架构
- 二、应用层:业务逻辑的载体
- 三、传输层:端到端的可靠保障
-
- 端口号:进程的唯一标识
- UDP协议:轻量无连接传输
- TCP协议:可靠的面向连接传输
-
- 协议格式
- 核心机制
-
- [1. 确认应答](#1. 确认应答)
- [2. 超时重传](#2. 超时重传)
- [3. 连接管理](#3. 连接管理)
- [4. 滑动窗口](#4. 滑动窗口)
- [5. 流量控制](#5. 流量控制)
- [6. 拥塞控制](#6. 拥塞控制)
- [7. 延迟应答与捎带应答](#7. 延迟应答与捎带应答)
- 面向字节流与粘包问题
- TCP与UDP对比
- 四、网络层:跨网段的路由导航
- 五、数据链路层:物理链路的传输基础
- 六、TCP/IP协议的实际应用与面试重点
- 七、总结
一、TCP/IP协议栈整体架构
TCP/IP协议栈采用分层模型,从上到下依次为应用层、传输层、网络层、数据链路层层和物理层。每一层都有明确的职责,通过层间接口协作完成数据传输,上层依赖下层提供的服务,下层为上层屏蔽实现细节。
- 应用层:面向具体业务,定义数据交互规则
- 传输层:端到端数据传输,负责可靠性、流量控制(核心协议为TCP、UDP)。
- 网络层:跨网段路由选择,定义IP地址及数据包转发规则。
- 数据链路层:物理链路数据传输,处理MAC地址、帧封装及ARP寻址。
这种分层设计的优势在于模块化清晰,某一层的技术升级不会影响其他层的正常工作,极大提升了协议的扩展性和维护性。
二、应用层:业务逻辑的载体
应用层是TCP/IP协议栈的最上层,直接面向用户需求,所有我们熟悉的网络应用都运行在这一层。
核心特点与作用
应用层的核心作用是定义特定业务的数据格式和交互流程,它不关心底层数据如何传输,只专注于满足业务需求。例如:
- 网页浏览依赖HTTP/HTTPS协议,定义了请求头、响应体的格式及状态码规则。
- 域名解析依赖DNS协议,实现域名到IP地址的映射,解决IP地址难记忆的问题。
- 文件传输依赖FTP、TFTP协议,规定了文件上传下载的步骤和数据编码方式。
我们之前编写的Java Socket程序也属于应用层,本质是通过自定义协议完成特定业务。
关键协议
- DNS:域名系统,底层使用UDP协议实现高效解析,浏览器会缓存DNS结果以提升访问速度。当输入URL后,浏览器首先通过DNS查询目标服务器IP,再发起后续连接。
- HTTP/HTTPS:超文本传输协议,HTTP基于TCP明文传输,HTTPS通过SSL/TLS加密,常用于网页、接口通信。
- FTP/SSH:FTP(21端口)用于文件传输,SSH(22端口)用于远程登录,均基于TCP实现可靠传输。
三、传输层:端到端的可靠保障
传输层位于应用层和网络层之间,负责将应用层数据可靠地从发送端传输到接收端,核心是端口号、TCP协议和UDP协议。
端口号:进程的唯一标识
端口号是传输层的核心概念,用于区分同一主机上的不同应用程序,与IP地址配合实现"端到端"通信。
核心特性
- 端口号范围:0-1023为知名端口号(如HTTP的80、HTTPS的443),由IANA分配;1024-65535为动态端口号,供客户端程序临时使用。
- 通信标识:通过"源IP+源端口+目的IP+目的端口+协议号"五元组唯一标识一个网络通信,可通过
netstat -n命令查看。
注意:
- 一个进程可以绑定多个端口号:例如服务器可同时监听80(HTTP)和443(HTTPS)端口。
- 一个端口号不能被多个进程绑定:端口号是进程的唯一标识,同一时间只能被一个进程占用。
UDP协议:轻量无连接传输
UDP(用户数据报协议)是一种简单的传输层协议,传输过程类似寄信,无需提前建立连接。
协议格式
UDP首部仅8字节,分成四个字段:源端口、目的端口、长度(整个数据报最大64K)和校验和(校验出错直接丢弃),每个字段各两字节,16位。
核心特点
- 无连接:知道对端IP和端口即可直接发送,无需三次握手。
- 不可靠:无确认应答和重传机制,数据丢失不会通知应用层。
- 面向数据报:应用层交付的报文原样发送,不拆分、不合并。
适用场景与注意事项
- 适用场景:实时性要求高、允许少量丢包的场景,如视频通话、语音聊天、DNS解析。
- 注意事项:若传输数据超过64K,需在应用层手动分包、拼装;基于UDP的应用层协议包括NFS、DHCP、DNS等。
TCP协议:可靠的面向连接传输
TCP(传输控制协议)是传输层的核心协议,专为可靠传输设计,通过一系列机制解决丢包、乱序、重传等问题,是大多数核心业务的首选。
协议格式

TCP首部最小20字节(4*5),最大60字节
- 16位源端口号与16位目的端口号:传输的核心内容
- 4位首部长度:4bit:0-15,由于选项存在,导致TCP报头长度是可变的。这里以4字节为单位。15对应的长度就是60字节
- 选项:补充信息,可有可无
- 32位序号/确认序号:用于按序传输和确认接收。
- 保留位:为未来扩展信息留出操作空间
- 6位标志位:SYN(建立连接)、ACK(确认应答)、FIN(关闭连接)、RST(重置连接)、PSH(立即推送)、URG(紧急数据)。
- 16位窗口大小:用于流量控制,告知发送端当前可接收的最大数据量。
核心机制
1. 确认应答
TCP为每个字节编号,编号是连续递增的。
在序号部分填写载荷部分第一个字节的序号;接收端收到数据后返回确认序号,填写收到的数据载荷最后一个字节序号+1,也就是表示<1001的数据都收到了,下一次从1001开始发送,确保数据不丢失。
TCP报头不参与编号,序号和确认序号都是针对载荷的
数据发送存在后发先至的情况,序号就可以为数据排序,保证应用程序通过socket api读到的数据(InputStream)顺序和对方写入的数据顺序(OutputStream)正确的。
TCP 会在接收方安排的接收缓冲区(内存中,操作系统内核里)通过网卡读到的数据,先放到缓冲区里面,后续代码调用read。再从缓冲区中读取。
缓冲区中根据序号排队,确保前面的数据收到,read才会解除阻塞;如果后面数据先到,read则会继续阻塞,不会读取数据。
基于TCP写代码不需要担心顺序问题,而基于UDP,实现拆包组包,需要考虑顺序,就会麻烦很多。
2. 超时重传
当A给B发送数据,在一定时间内A没有收到ACK,A就认为发生丢包了。
通过引入超时时间来判断是否丢包。发送端未在规定时间内收到确认,会重传数据。超时时间动态调整,初始为500ms,重传后按2倍、4倍递增,累计多次失败则关闭连接。
当超时次数或者等待时间达到一定限度,就会认为是网络出现故障,放弃这次传输。
当A没有收到ACK,可能是 A->B 发送数据过程中丢包,也可能是 B->A 返回ACK过程中丢包。但是A无法判断是哪种情况,都会进行重传。
- 如果是 A->B 数据丢失,重传可以解决;
- 如果 B->A 过程中ACK丢失,A再重传,就会导致B收到两份一样的数据。在接收缓冲区会根据序号进行去重操作(排序操作),如果存在则丢弃;不存在则放入。保证应用程序只收到一份数据。
确认应答 和超时重传是TCP最核心的两个机制,保证了TCP进行可靠传输。
3. 连接管理
通过三次握手建立连接,四次挥手关闭连接。握手或挥手操作发送不携带业务的数据,通过这个数据"跟对方打个招呼"。
(1) 建立连接
SYN是指synchronized,同步。与多线程的概念不同,这里的同步指"数据上的同步",A告诉B,接下来我要和你建立连接,需要你把我的关键信息保存下来,同时你也要把你的信息同步给我。把TCP报头的SYN部位填1,表示同步报文。
B确认应答ack和发送syn可以合并,这样就是"三次握手"。

注意:
- 关键信息包括IP 和端口号。IP保存在携带着TCP的IP报头中;端口号保存在TCP报头中。而sync和ack都不携带载荷。
- 客户端发起syn。客户端和服务器只是角色,同一程序在不同场景可以扮演不同角色,主动的一方是客户端。
- syn和ack都是内核负责的,与用户代码无关。可以保证是同一时机发送,这样就可以合并。

思考: 三次握手有什么意义?解决了哪些问题?
- 三次握手相当于"投石问路",先初步探查网络的通信链路是否通畅。
- 验证通信双方发送能力和接收能力是否正常。
如果只握手两次,无法让双方都确认收发能力正常,因此三次握手是必不可少的。而四次握手又没必要。 - 协商一些关键信息。例如序号从几开始。
初始序号一般不从0开始,因为传输过程中存在丢包现象。
举个例子:第一次传输由1000开始,这过程中可能有数据迷路;第二次传输由8000开始,如果此时第一次传输中迷路的数据才到达,就可以很好的判断出这不是有用的数据,可以丢弃。
(2)断开连接
四次挥手不可以合并,因为ACK和FIN两次交互的时机不一定相同。内核收到FIN会第一时间返回ACK,与应用程序的代码无关;第二个FIN则是代码调用socket.close或者进程结束才会触发。第二个FIN与ACK很可能不处于同一时机。
三次握手中,一定是客户端主动发起SYN(第一次握手一定是客户端开头);四次挥手中,客户端与服务端都可以主动发起FIN,取决于谁先调用close,实际开发中,客户端主动断开连接的可能性比较大。

借助TCP服务器部分的代码理解四次回挥手:

异常情况:服务器始终不调用close,站在A的视角上,A已经给B把FIN发了很久,B没有后续的挥手操作,A就会主动释放连接(也就是把B的核心信息删掉);站在B的视角上,由于代码有bug,连接还存在,虽然还保存对方信息,但是无法进行正常的数据通信了
4. 滑动窗口
无需等待每段数据的ACK,可连续发送多个数据段,提升传输效率。窗口大小越大,吞吐量越高,由操作系统通过发送缓冲区维护。

一直持续发送,不等待,显然是不科学的,因为这样就没有可靠性了

如果2001ack比1001先到,那么就不需要等待1001ack,直接往后走两个格子就行。因为确认序号本身的含义就是当前序号之前的数据全部收到,可以从当前序号开始发送。2001ack本身就包含1001ack。
注意:
- 窗口越大,批发量数据就越多,效率就越高。但是窗口不能无限大,会影响可靠性。
- 滑动窗口只是在可靠传输的基础上提高效率。引入可靠性肯定会使效率折损,不可能会比UDP还高。
丢包问题:
-
丢ack

后一个ack可以涵盖前一个ack,因此不需要做任何处理
-
丢数据

快速重传: 只是谁丢了,就重传谁,其他已收到的数据无需再重传,整个重传过程是很快的
注意: 超时重传和快速重传是针对不同情况的重传机制,并不矛盾。
- 超时重传:传输的数据量小,没有构成滑动窗口的批量传输机制
- 快速重传:传输的数据量大,可以形成滑动窗口
5. 流量控制
滑动窗口,窗口越大,效率就越高。但窗口不能无限大,接收方的处理能力是有上限的,这里的上限与代码逻辑有关。
把接收缓冲区理解为蓄水池,发送的速度就相当于蓄水的速度;应用程序从缓冲区汇总读取数据就相当于放水(每读一个字节,就可以把这个字节从缓冲区中删除了)。如果"水溢出"就会丢包。
补充:
- 每个
Socket对象都对应一组接收缓冲区和发送缓冲区。也就是说一个程序创建了N个Socket对象就会有N个发送缓冲区和接收缓冲区。 - 在Java中创建
Socket对象(Socket clientSocket = new Socket())内核中的文件描述符表就会多一项文件对象,这个文件对象包括发送缓冲区和接收缓冲区(都是字节数组)
流量控制就是让发送方"踩刹车",
接收端通过窗口大小字段告知发送端自身缓冲区状态,避免发送过快导致缓冲区溢出。缓冲区满时窗口置为0,发送端停止发送并定期探测。
6. 拥塞控制
通过慢启动、拥塞避免、快重传、快恢复机制,避免网络拥堵。慢启动阶段拥塞窗口指数增长,超过阈值后线性增长,丢包时调整阈值并重置窗口。
7. 延迟应答与捎带应答
延迟应答(200ms内或每接收2个包应答)可增大窗口大小;捎带应答将ACK与应用层数据一起发送,减少网络开销。
面向字节流与粘包问题
- 面向字节流:TCP将应用层数据视为连续字节流,通过发送缓冲区和接收缓冲区实现读写解耦。例如发送端分10次写1字节,接收端可一次读10字节。
- 粘包问题:TCP无数据边界,应用层需自行定义边界,解决方案包括:定长包、包头加长度字段、使用分隔符。
TCP与UDP对比
| 特性 | TCP | UDP |
|---|---|---|
| 连接方式 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠(确认、重传、排序) | 不可靠(无确认重传) |
| 传输效率 | 较低(机制复杂、开销大) | 较高(首部简单、无开销) |
| 适用场景 | 文件传输、接口通信、登录 | 视频通话、语音、DNS解析 |
四、网络层:跨网段的路由导航
网络层的核心作用是在复杂网络中找到合适的传输路径,实现跨网段数据转发,核心是IP协议、地址管理和路由选择。
IP协议:网络层的核心
IP协议定义了IP地址格式和数据包转发规则,是跨网段通信的基础。
协议格式
IP首部最小20字节,关键字段包括:
- 版本号:IPv4(32位地址)和IPv6(128位地址),目前IPv6正在逐步普及。
- 总长度:IP数据包总字节数,最大65535字节。
- TTL(生存时间):默认64,每经过一个路由器减1,避免路由循环导致数据包无限转发。
- 源IP/目的IP:标识发送端和接收端的网络地址。
核心功能
- 地址标识:通过IP地址唯一标识网络中的主机或路由器。
- 路由转发:路由器收到IP数据包后,根据目的IP查询路由表,转发到下一跳。
地址管理:IP地址的分配与划分
IP地址是网络层的核心标识,分为网络号和主机号两部分,用于区分不同网段和同一网段内的主机。
分类与CIDR
- 传统分类:将IP分为A、B、C、D、E类,A类(0.0.0.0-127.255.255.255)适用于大型网络,B类(128.0.0.0-191.255.255.255)适用于中型网络,但存在地址浪费问题。
- CIDR(无类域间路由):通过子网掩码区分网络号和主机号,例如192.168.1.1/24表示子网掩码前24位为1(255.255.255.0),网络号为192.168.1.0,主机号范围0-255。
私有IP与公网IP
- 私有IP:用于局域网内部通信,无需注册,包括10.、172.16.-31.、192.168.*,不同局域网可重复使用。
- 公网IP:用于互联网通信,全球唯一,需向运营商申请。
IP地址不足的解决方案
- DHCP:动态分配IP地址,仅给接入设备分配地址,提高利用率。
- NAT:网络地址转换,路由器将私有IP转为公网IP,实现多设备共享一个公网IP。
- IPv6:128位地址空间,彻底解决IP不足问题,我国IPv6活跃用户数已达7.67亿。
路由选择:跨网段的路径规划
路由选择是网络层的核心功能,指路由器根据路由表确定IP数据包的转发路径,过程类似"一跳一跳问路"。
路由表
路由器维护一张路由表,包含目的网络地址、子网掩码、下一跳地址、发送接口等信息,可通过route命令查看。
- 直连路由:目的网络与路由器直接相连,无需转发。
- 静态路由:由管理员手动配置。
- 动态路由:通过路由协议(如OSPF、RIP)自动生成。
转发过程
以目的IP为202.10.1.2为例:
- 主机查询路由表,发现无匹配条目。
- 按默认路由将数据包发送到网关路由器(如192.168.10.1)。
- 网关路由器根据自身路由表转发数据包,依次经过多个路由器,最终到达目标主机。
五、数据链路层:物理链路的传输基础
数据链路层位于网络层之下,负责处理物理链路的帧封装、MAC地址寻址、MTU限制等问题,确保数据在相邻设备间可靠传输。
以太网:主流的局域网技术
以太网是数据链路层的主流技术标准,规定了网线类型(双绞线)、传输速率(10M/100M/1000M)、帧格式等。
以太网帧格式
以太网帧长度为46-1500字节,核心字段包括:
- 目的MAC/源MAC:6字节,网卡出厂固化的硬件地址,用于相邻设备寻址。
- 类型字段:标识上层协议(如0800对应IP协议)。
- CRC校验码:验证帧数据的完整性,校验出错则丢弃。
MAC地址与IP地址的区别
- IP地址:描述"终点地址",类似快递的收件人地址,跨网段有效。
- MAC地址:描述"区间起点/终点",类似快递的每一段运输节点地址,仅在相邻设备间有效。
例如:从主机A发送数据到外网主机B,IP地址始终是A和B的地址,而MAC地址在每一跳都会变为当前路由器和下一跳路由器的地址。
MTU:最大传输单元
MTU是数据链路层对帧数据的最大限制,以太网MTU为1500字节,超过则需分片。
对上层协议的影响
- IP协议:超过MTU的IP数据包会被分片,每个分片有相同的标识号,接收端重组后交给上层。任意分片丢失则重组失败,IP层不负责重传。
- UDP协议:UDP数据报最大长度为64K,若数据超过1472字节(1500-20IP首部-8UDP首部),会被IP分片,丢失概率增加,因此UDP适合传输小包。
- TCP协议:通过MSS(最大分段大小)协商避免分片,MSS=MTU-IP首部-TCP首部,建立连接时双方通过SYN报文告知自身MSS,选择较小值作为最终标准。
ARP协议:IP与MAC的映射桥梁
ARP(地址解析协议)介于数据链路层和网络层之间,负责将IP地址转换为MAC地址,解决"知道IP但不知道MAC"的寻址问题。
工作流程
- 主机A想与主机B(IP:172.20.1.2)通信,查询本地ARP缓存表,若无B的MAC地址,则发送ARP广播(目的MAC:FF:FF:FF:FF:FF:FF)。
- 同一网段内所有主机接收广播,仅主机B发现IP匹配,返回ARP应答,包含自身MAC地址。
- 主机A将B的IP-MAC映射存入ARP缓存表(过期时间20分钟),后续通信直接使用该映射。
六、TCP/IP协议的实际应用与面试重点
经典应用场景
- 服务器开发:需深入理解TCP的连接管理、滑动窗口、拥塞控制,避免CLOSE_WAIT状态堆积(需正确调用close关闭socket)。
- 网络编程:UDP适合实时通信,需手动处理分包、重传;TCP适合可靠传输,需解决粘包问题(定长包、长度字段、分隔符)。
- 网络故障排查:通过
netstat查看连接状态,arp -a查看ARP缓存,route查看路由表,定位丢包、连接失败等问题。
高频面试题解析
- TCP三次握手和四次挥手的原因:三次握手确保双方收发能力正常,四次挥手因TCP全双工,需分别关闭发送和接收通道。
- TIME_WAIT状态的作用:持续2MSL(报文最大生存时间),确保迟到的报文消失,避免端口复用导致的数据错误。
- 用UDP实现可靠传输:参考TCP机制,在应用层实现序列号、确认应答、超时重传、滑动窗口等功能。
- NAT的优缺点:优点是解决IP不足,无需更新硬件;缺点是无法从外部访问内部服务器,转换表维护有开销。
七、总结
TCP/IP协议栈是一个层层递进、相互协作的复杂系统,每一层都有明确的职责和核心技术:
- 应用层定义业务规则,是协议栈的"上层建筑"。
- 传输层通过TCP/UDP和端口号,实现端到端的可靠或高效传输。
- 网络层通过IP地址和路由选择,实现跨网段的路径规划。
- 数据链路层通过MAC地址和帧封装,实现物理链路的可靠传输。