传输层(Transport Layer)
传输层(Transport Layer):通过 端口机制 和 端到端逻辑信道,实现了真正意义上的进程间通信。传输层协议仅在网络边缘的主机中实现,路由器、交换机等网络核心设备仅处理下三层(网络层、数据链路层、物理层)
- TCP:提供面向连接、可靠的服务(如数据重传、流量控制)
- UDP:提供无连接、尽力而为的服务(适用于实时视频等低延迟场景)
运输层通过端口号标识进程,使数据能够准确交付给目标应用(如HTTP默认端口80)
端口号分类
知名端口(Well-Known Ports):
0-1023
, 这些端口通常被分配给系统级的服务和应用程序,如HTTP (80), HTTPS (443), FTP (21), SSH (22)等。注册端口(Registered Ports):
1024-49151
,可以由用户进程或应用程序动态选择,但通常用于特定的应用程序或服务,这些应用需要向IANA(互联网号码分配机构)注册以避免冲突动态/私有端口(Dynamic/Private Ports):
49152-65535
,通常用于临时连接,当客户端发起请求时,操作系统会自动为该连接分配一个未使用的端口号。
若要检查某个端口是否已被占用,可以根据所用的操作系统选择合适的命令进行查询
netstat -tuln
ss -tuln
netstat -anp | grep port
lsof -i:port
lsof -i -P | grep 3306
用户可自由选择的端口号主要是从49152到65535的动态/私有端口区间。开发过程中,为了确保端口不冲突,建议先确认所需使用的端口是否空闲
Transmission Control
传输控制协议(TCP,Transmission Control Protocol) 提供了一种可靠的、面向连接的服务,用于在网络上的不同主机之间传输数据。TCP确保数据能够准确无误地从源端传递到目的端,并且按正确的顺序重组。
面向连接:通信前需要建立连接(三次握手),通信结束后释放连接(四次挥手)。
可靠传输:通过确认机制、重传机制、流量控制和拥塞控制确保数据可靠传输。
全双工通信:双方可以同时发送和接收数据。
字节流服务:将数据视为无结构的字节流,不保留消息边界。
应用场景:需要可靠传输的应用,如HTTP、FTP、SMTP等。
TCP协议数据报
TCP数据报(TCP段)由首部和数据两部分组成。首部长度为20字节(无选项时),最大长度为60字节(含选项)。

注意:TCP并不以报文段为单位来编号,而是对每个字节进行编号。这意味着每一个发送出去的字节都有一个唯一的序列号
Source Port(源端口):标识发送方的应用程序端口号,通常由客户端临时分配
Destination Port(目标端口):标识接收方的应用程序端口号(对应服务器上的特定服务)
Sequence Number(序列号):标识了该报文段中第一个字节的数据在整个数据流中的位置。例:假设客户端想要发送一段较长的消息给服务器,这条消息被分割成若干个TCP报文段发送:
- 客户端首先发送一个报文段,假设序列号设为seq=1000,长度为1000字节(即包含字节1000至1999)。注意:初始序列号(ISN, Initial Sequence Number)并不是固定从0开始的,而是为了减少被攻击的风险由操作系统根据一定的算法生成的
- 如果服务器成功接收了这个报文段,它将回复一个ACK报文,其中ack=2000,表明它期待下一个报文段的起始序列号为2000。
- 客户端接着发送下一个报文段,序列号为seq=2000,长度也为1000字节(即包含字节2000至2999)
Acknowledgment Number(确认号):期望接收的下一个字节的序列号,仅当ACK标志置1时有效。例:如果接收方收到了序列号范围从seq=1000到seq=1999的所有字节,则它会在回复的ACK报文中设置ack=2000,告诉发送方它希望接下来收到序列号为2000及之后的数据
数据偏移(Data Offset)/首部长度(Header Length):表示TCP首部的长度,单位为4字节。最小值为5(对应20字节),最大值为15(对应60字节)
Reserved(保留字段):保留供未来使用,必须为0。目前部分被用于显式拥塞通知(ECN)
Control Flags(控制标志):用于控制TCP连接的状态和数据传输
- URG(Urgent):置1时,紧急指针有效,指示紧急数据的位置。紧急数据直接传递至应用层,不进入接收缓冲区
- ACK(Acknowledgment):置1时,确认号字段有效
- PSH(Push):要求接收方立即处理数据,而非缓存,接收方应立即将数据交给应用层
- RST(Reset):重置连接(强制终止异常连接)
- SYN(Synchronize):用于连接建立,同步初始序列号
- FIN(Finish):用于正常关闭连接,表示数据发送完毕
Window Size(窗口大小):流量控制的关键字段,表示接收方可接收的数据量(单位:字节),通过滑动窗口机制动态调整发送速率,避免接收方缓冲区溢出
Checksum(校验和):验证TCP首部、数据及伪头部(包含IP)的完整性,检测传输错误
Urgent Pointer(紧急指针):指示紧急数据在数据流中的结束位置(仅在URG标志为1时有效),实际应用较少,部分实现可能忽略此字段
Options(选项):提供额外的功能。常见选项:MSS(Maximum Segment Size):协商数据段的最大长度,SACK(Selective Acknowledgment):允许接收方指明已接收的非连续数据块,Timestamp:用于计算往返时间(RTT)和防止序号回绕
填充(Padding):确保选项字段的总长度为4字节的整数倍,通过填充0实现
TCP连接的建立
TCP是面向连接的协议,进行通信之前必须先建立连接(三次握手)。这个过程中涉及到以下几个关键TCP报文首部字段及其变化:
- 源端口号(Source Port)和目的端口号(Destination Port)
- 序列号(Sequence Number, 32位):对于SYN报文段,此值代表初始序列号(ISN)
- 确认号(Acknowledgment Number, 32位):期望接收的下一个字节的序列号
- 标志位(Flags): SYN-同步序列号,用于发起连接请求, ACK-确认字符有效, FIN-终止连接
建立连接之前 服务端持续监听特定端口(LISTEN
状态),等待客户端发起连接请求
TCP连接状态
TCP连接的状态包括: CLOSED
(关闭)、LISTEN
(监听)、SYN_SENT
(等待对方的确认)、SYN_RCVD
(收到SYN后的状态)、ESTABLISHED
(已建立连接)、FIN_WAIT_1/2
、TIME_WAIT
等
注:在下面建立连接的描述过程中,SYN、ACK指的是标志位(Flag bits),而序列号(Sequence Number)和确认号(Acknowledgment Number)则是具体的32位数值字段,为了简洁常记作:序列号seq
和 确认号 ack

TCP建立连接的过程(三次握手)
- 第一次握手(SYN):客户端主动发送一个SYN报文段到服务端(状态变化:
CLOSED
-->SYN_SENT
)
- 设置SYN标志位为1
- 生成一个初始序列号(假设为
x
),并将其放在序列号(Sequence Number)字段中
- 第二次握手(SYN+ACK):服务端收到SYN报文后,知道客户端想要建立连接,发送一个SYN+ACK报文段给客户端。状态变化:
LISTEN
-->SYN_RCVD
- 设置SYN和ACK标志位为1
- 生成自己的初始序列号(假设为
y
),设置序列号(Sequence Number)字段设为y
- 确认号(Acknowledgment Number)字段设为
x+1
- 第三次握手(ACK):客户端动收到SYN+ACK报文段后,发送一个ACK报文段作为响应,确认了服务端同意建立连接
- 设置ACK标志位为1
- 序列号(Sequence Number)字段设为
x+1
- 确认号(Acknowledgment Number)字段设为
y+1
可以带上第一个数据包,但通常不包含应用层数据
最终双方都进入ESTABLISHED
状态,表明连接已经成功建立,可以开始数据传输。
TCP连接的终止
四次挥手(Four-Way Handshake)即TCP连接终止的过程,用于确保双方都能安全地关闭连接。由于TCP连接是全双工的(即数据可以在两个方向上同时传输),因此每一方都需要独立地通知对方自己已经完成了数据发送并准备好关闭连接。
四次挥手过程中的关键字段:
- FIN (Finish):标志位,表示发送端已经完成数据发送,希望断开连接。
- ACK (Acknowledgment):标志位,确认字符有效。
- Sequence Number (序列号):标识该报文段中第一个字节的数据在整个数据流中的位置
- Acknowledgment Number (确认号):表示期望收到对方下一个报文段的第一个数据字节的序号
理论上客户端和服务器都可以发起主动关闭,但是更多的情况下是客户端主动发起

四次挥手(Four-Way Handshake)
第一次挥手(FIN from Client)
客户端:发送一个FIN报文段给服务器。状态从
ESTABLISHED
变为FIN_WAIT_1
- 设置FIN标志位为1
- 序列号设为
u
(假设这是客户端最后一个已发送的数据包的序列号)
服务器动作: 收到FIN报文后,知道客户端不再发送数据了。状态保持在
ESTABLISHED
状态,直到准备关闭自己的发送通道。
第二次挥手(ACK from Server)
服务器:发送一个ACK报文段给客户端作为响应。状态从
ESTABLISHED
变为CLOSE_WAIT
- 设置ACK标志位为1
- 确认号设为
u+1
(因为客户端希望收到的下一个字节是u+1
)
客户端: 收到ACK报文后,确认服务器已经收到了关闭请求。状态
FIN_WAIT_1
变为FIN_WAIT_2
第三次挥手(FIN from Server)
当服务器也完成所有数据发送时,发送一个FIN报文段给客户端。状态从
CLOSE_WAIT
变为LAST_ACK
- 设置FIN标志位为1
- 设置ACK标志位为1
- 序列号设为
v
(假设这是服务器最后一个已发送的数据包的序列号)
客户端:收到FIN报文后,知道服务器也不再发送数据了,状态保持在
FIN_WAIT_2
状态
第四次挥手(ACK from Client)
客户端:发送一个ACK报文段给服务器作为响应
- 设置ACK标志位为1
- 确认号设为
v+1
(因为服务器希望收到的下一个字节是v+1
) - 状态:从
FIN_WAIT_2
变为TIME_WAIT
,等待一段时间(通常是最大分段寿命的两倍,以确保网络上的所有报文都被清除)后进入CLOSED
状态
服务器: 收到ACK报文后,确认客户端已经收到了关闭请求。状态从
LAST_ACK
变为CLOSED
实际场景下会断开连接的情况
正常关闭:当应用程序逻辑决定不再需要维持连接时,例如用户关闭浏览器标签页或退出应用程序。
超时:如果一方在一定时间内没有收到另一方的任何数据或心跳信号(如TCP Keepalive机制),可能会认为连接已失效,并主动发起关闭请求。
资源限制:当系统资源达到上限(如文件描述符数量、内存等),操作系统可能强制关闭某些连接以释放资源。
错误处理:如果检测到严重的协议错误(如接收到无法解析的数据包),可能会触发连接关闭以防止进一步的问题。
异常断电或崩溃:物理层面上的中断(如电源故障、硬件损坏)或者软件层面的崩溃(如进程意外终止)也会导致连接被断开。
MSS和MTU
MSS,即最大段大小(Maximum Segment Size),是指在TCP连接中,一个TCP报文段(不包括TCP和IP头部)所能承载的最大数据量。TCP通过MSS确保每个段封装成IP数据报时不超MTU,避免IP分片,因为IP分片会增加网络复杂性和潜在的数据丢失风险
MSS 和 选项字段
MSS是在TCP三次握手期间通过SYN和SYN/ACK报文中的选项字段(Options Field)进行协商的
MSS Option: Kind=2, Length=4, MSS Value=1460
- Kind (1字节):表示这是一个MSS选项,值为2
- Length (1字节):表示整个选项的长度,对于MSS选项来说,长度固定为4字节
- MSS Value (2字节):表示建议的最大段大小,单位是字节
客户端和服务端都可以提出自己的MSS值,最终双方会选择较小的那个值作为通信的基础
MSS值通常为 MTU - IP头(20字节) - TCP头(20字节)
例如 MTU为1500字节,则MSS为1460字节
MTU(最大传输单元,Maximum Transmission Unit) 指网络中每个数据帧的最大长度(以字节为单位),这是在特定链路层技术下允许的最大数据包大小。
MTU由物理网络介质和技术决定,以太网(Ethernet)典型的MTU值是1500字节
TCP重传机制
TCP重传机制用于确保丢失或损坏的数据包能够被重新发送并正确接收
超时重传(Timeout Retransmission):当发送方发送一个数据段后,会启动一个定时器(称为重传定时器)。如果在定时器到期之前没有收到该数据段的确认(ACK),则认为该数据段可能丢失,并触发重传
超时重传(Timeout Retransmission)示例
假设发送方发送了一个序列号为seq=1000的数据段,并设置了超时时间为1秒。如果在1秒内没有收到对应的ACK,发送方将重传该数据段
发送方 -> [seq=1000] -> 网络
(1秒后无响应)
发送方 -> [seq=1000] -> 网络
Retransmission Timeout (RTO):重传超时时间,由TCP根据网络状况动态调整
快速重传(Fast Retransmit):快速重传是一种优化机制,允许发送方在不等待定时器超时的情况下更快地检测到数据段丢失。具体来说,如果发送方连续收到三个重复的ACK(即接收方已经收到了后续的数据段但未收到某个中间的数据段),则立即重传这个丢失的数据段
快速重传(Fast Retransmit)示例
假设发送方发送了序列号分别为seq=1000
、seq=1050
、seq=1100
的数据段。接收方收到seq=1050
和seq=1100
,但未收到seq=1000
,因此发送重复的ACK:
接收方 -> [ack=1000] -> 发送方
接收方 -> [ack=1000] -> 发送方
接收方 -> [ack=1000] -> 发送方
当发送方收到第三个重复的ACK时,立即重传seq=1000
的数据段
Sliding Window
在滑动窗口机制出现之前,TCP使用 停等协议(Stop-and-Wait),发送方每发送一个数据段后必须等待确认,效率低下。为了提高传输效率,滑动窗口机制被引入,允许发送方连续发送多个数据段,而不必等待每个数据段的确认
滑动窗口(Sliding Window) 机制主要用于提高效率和实现流量控制,确保发送方不会以超过接收方处理能力的速度发送数据,从而避免接收方缓冲区溢出导致的数据丢失
接收方窗口大小(Receiver Window Size),也称为接收窗口或简称 rwnd ,指的是接收方当前可以接受的最大未确认数据量,这个值由接收方根据其缓冲区状态动态调整,并通过TCP报文中的窗口字段告知发送方
发送窗口可分为四个区:

滑动机制:发送方维护一个发送窗口(其中包含已经发送但尚未被确认的数据包),发送方可以在不等待确认的情况下继续发送新的数据包,直到发送窗口填满。随着接收方ACK确认,窗口右移,释放空间发送新数据
发送与确认:发送方将数据包发送到接收方。接收方收到数据包后,向发送方发送一个确认(ACK),表示已成功接收该数据包,接收方通常会累积多个数据包的确认,只在接收到所有预期的数据包后才发送一次确认
正常情况下的ACK确认和窗口大小调整:
- 接收方根据自身的处理能力和缓冲区状态设定一个窗口大小,并在每个ACK中通知发送方。如果接收方处理能力强、缓冲区空间大,则会设置较大的窗口值,反之则设置较小的窗口值以限制发送速率
- 通过动态调整window size,接收方能够有效地控制来自发送方的数据流,确保自身不会因为过载而丢弃数据包
丢失或乱序到达的数据包处理:
- 如果某些数据包丢失或者乱序到达,接收方仅对已连续接收到的最大序列号的数据包进行确认(即最大连续序号)。这意味着即使接收到了后续的数据包,但中间有丢失的数据包未被接收时,接收方不会对这些后续的数据包进行确认
- 对于发送方来说,若在超时时间内未收到某个数据包的确认,它将重传该数据包以及所有尚未被确认的数据包(根据具体的重传策略可能有所不同)
滑动窗口协议通过动态调整发送方和接收方之间的窗口大小(window size)来实现高效的通信,并允许接收方根据其处理能力或网络状况灵活地调整流量
窗口缩放选项(Window Scale Option)
传统的TCP头部只有16位用于表示接收窗口大小,这意味着最大的窗口大小为65535字节。为了支持更高速率的传输,TCP引入了窗口缩放选项(Window Scale Option),允许窗口大小扩展到更大的值。窗口缩放因子(Window Scale)是通过TCP 选项
字段进行协商的。窗口缩放因子的选项格式为:
- Kind (1字节):值为3。
- Length (1字节):值为3。
- Shift Count (1字节):表示窗口大小左移的位数(即缩放因子),范围通常是0到14之间
假设缩放因子为6,这意味着实际窗口大小将是TCP报文中窗口字段值乘以
Window Scale 和 Window Size 的值是基于接收方当前可用的缓冲区空间动态确定的
Flow Control
流量控制(Flow Control):防止发送方发送数据的速度超过接收方处理数据的能力,避免接收方因缓冲区溢出而丢弃数据。
基于窗口的机制:接收方通过ACK报文中携带的窗口大小字段通知发送方当前能接受的最大数据量。发送方据此调整自己的发送速率,确保不会超出接收方的处理能力。
动态调整:随着接收方处理完更多的数据,它会相应地增加窗口大小;反之亦然。
数据传输期间发送方只能发送不超过接收方窗口大小的数据量。一旦窗口满载,发送方必须停止发送直到接收到新的ACK并得知窗口有空余
TCP拥塞控制
拥塞控制(Congestion Control):是一种用于防止网络过载并确保高效数据传输的机制。随着互联网规模和复杂性的增长,如何有效地管理网络资源成为了一个关键问题。TCP拥塞控制通过一系列算法来动态调整发送方的数据发送速率,以适应当前网络状况,避免因过多的数据包导致网络拥塞。
拥塞控制的目标
- 提高吞吐量:最大化利用可用带宽。
- 减少延迟:尽量减小数据包在网络中的排队时间。
- 公平性:保证多个流共享同一链路时能够公平地分配带宽。
主要的拥塞控制算法
慢启动(Slow Start)
- 在连接建立或超时后开始,初始拥塞窗口(cwnd, Congestion Window)设为较小值(通常是一个最大段大小MSS)。
- 发送方每收到一个ACK确认,就将cwnd增加一个MSS的大小,即指数增长。
- 当cwnd达到慢启动阈值(ssthresh)或者出现丢包时,进入拥塞避免阶段。
拥塞避免(Congestion Avoidance)
- 一旦cwnd达到ssthresh,便进入这个阶段。
- 相比于慢启动的指数增长,拥塞避免阶段cwnd的增长速度较慢,每经过一个往返时间RTT才增加一个MSS的大小。
- 如果检测到丢包,则会降低ssthresh,并根据具体策略调整cwnd大小。
快速重传(Fast Retransmit)
- 当发送方连续收到三个对相同未确认数据段的重复ACK时,认为该段丢失,无需等待重传计时器到期即可立即重传丢失的数据段。
快速恢复(Fast Recovery)
- 在快速重传之后,不执行慢启动而是直接进入拥塞避免阶段,避免了效率低下的重新开始慢启动过程。
- 快速恢复通过维持较高的cwnd值,同时基于接收到的重复ACK进行适当调整,帮助快速恢复至正常状态。
其他改进和技术
- 选择性确认(Selective Acknowledgment, SACK):允许接收方告知发送方哪些数据段已成功接收,使得发送方只需重传丢失的数据段而非所有后续数据段。
- TCP窗口缩放选项:为了支持更大数据量的传输,尤其是对于高带宽延迟积的产品,允许使用更大的窗口尺寸。
- ECN(显式拥塞通知):一种让路由器在不丢弃数据包的情况下向发送方指示网络拥塞的方法,有助于更平滑地调整发送速率。
User Datagram Protocol
UDP(User Datagram Protocol,用户数据报协议)是一种无连接的、不可靠的传输层协议。
- 无连接:UDP不建立连接,直接发送数据报,减少了握手过程带来的延迟。
- 不可靠传输:没有确认机制、重传机制或流量控制,可能导致数据丢失、重复或乱序。
- 快速高效:由于缺少复杂的控制机制,UDP头小且处理速度快,适合需要低延迟的应用。
- 支持广播和多播:能够向多个目的地发送单个数据报,适用于特定的网络应用。
与TCP相比,UDP不提供连接管理、数据重传或排序等功能,但它具有较低的开销和较高的效率,适用于对实时性要求较高但对少量丢包不太敏感的应用场景,如视频流、语音通话、DNS查询等。
UDP数据报格式
一个UDP数据报由两部分组成:头部(Header)和数据(Data)。UDP头部非常简单,固定8个字节(64位),这使得它比TCP更轻量级

源端口号(Source Port, 16 bits):标识发送该UDP数据报的应用程序端口。在客户端发起请求时会使用随机分配的高编号端口。
目标端口号(Destination Port, 16 bits):标识接收方的应用程序端口号
长度(Length, 16 bits):整个UDP数据报的长度,包括头部和数据部分。最小值为8(仅包含头部),最大值受限于IPv4或IPv6的最大传输单元(MTU)。
校验和(Checksum, 16 bits):用于验证数据报的完整性和准确性
使用场景示例
- 实时音视频传输:如VoIP电话、在线直播等,对延迟敏感,少量数据丢失不会严重影响用户体验。
- 域名系统(DNS):查询请求短且频繁,UDP提供了足够的速度和效率。
- 游戏服务器通信:快速响应的游戏互动,偶尔的数据丢失可通过游戏逻辑弥补。
尽管UDP不具备TCP那样的可靠性,但其简洁的设计使其成为许多高性能、实时应用的理想选择
UDP伪首部和校验和
伪首部是计算 UDP校验和 时临时构造的一个数据结构,用于增强校验和的可靠性。
- 伪首部仅在 校验和 计算时使用,不会出现在实际的IP数据报或UDP数据报中
- 伪首部的构造和校验和的计算由操作系统的网络协议栈完成,应用程序无需直接处理
伪首部由以下字段组成,共12字节:

- Source IP Address(源IP地址): 32位,表示IP数据报的源IP地址
- Destination IP Address(目标IP地址): 32位,表示IP数据报的目标IP地址
- Zero(保留字段): 8位,必须为
0
- Protocol(协议类型): 8位,表示上层协议类型(UDP的协议号为
17
) - UDP Length(UDP长度):16位,表示UDP数据报的总长度(包括首部和数据)
伪首部和校验和的工作流程
发送端流程:
- 构造伪首部:操作系统根据IP层提供的源IP地址、目标IP地址等信息构造伪首部。
- 计算校验和:
- 将伪首部、UDP首部和UDP数据拼接成一个临时数据块。
- 对临时数据块按16位为单位进行反码求和,结果取反作为校验和。
- 将校验和存入UDP首部的校验和字段。
- 封装并发送: 丢弃伪首部,将UDP首部和数据封装进IP数据报,通过网络层发送。
接收端流程:
- 提取数据报: 网络层接收到IP数据报,解封装后提取出UDP首部和数据部分
- 重构伪首部: 根据接收到的IP数据报中的源IP地址、目标IP地址等信息,重新构造伪首部
- 验证校验和:
- 将伪首部、UDP首部和数据拼接成一个临时数据块
- 对临时数据块按16位为单位进行反码求和
- 如果计算结果为全1(即
0xFFFF
),则校验和正确;否则,数据报被丢弃
伪首部中的源IP地址和目标IP地址从IP数据报的IP首部中提取。协议类型和UDP长度由操作系统根据具体情况确定。伪首部不是IP数据报的一部分,网络层只处理实际的IP数据报传输