一、什么是TCP、UDP
TCP(Transmission Control Protocol):面向连接、可靠、有序、带流量/拥塞控制的字节流协议。用于需要可靠传输的场景(HTTP、FTP、SSH 等)。
UDP(User Datagram Protocol):无连接、不可靠、无顺序保证、开销小的报文协议。适合实时、延迟敏感或可容忍丢包的场景(DNS、RTP、游戏、DHCP)。
二、协议定位与作用
都属于传输层,位于TCP/IP四层模型的传输层、OSI七层模型的传输层。为应用层提供端到端的数据传输服务。
三、TCP
名词介绍
-
SYN(Synchronize):同步标识,SYN是TCP头部中的一个标识位(flag),用于请求建立连接,表示发送方想要同步序列号,以便后续数据传输的可靠有序。SYN=1是一个标识(flag)表示请求同步序列号,在建立TCP连接的时候的信号,如果=0表示不请求同步,通常在已经建立了连接中使用。
-
ACK(Acknowledgment):ACK 是 TCP 头部中的标识位(ACK=1),用于确认收到对方的包。ACK=1是一个标识(flag)表示发送方正在确认它已经收到对方的某些数据,如果=0则表示ACK无效(通常忽略),包括不被视为确认响应。在初始连接阶段常见,因为没有什么需要确认的。
-
FIN(Finish):发送方请求结束数据传输通道,标志着连接关闭过程的开始。=1 表示这个标志位被激活,意味着发送方请求“结束发送数据通道”。它通知接收方:“我没有更多数据要发送了,但你可以继续发给我”(半关闭,half-close)。
如果FIN=0,则不请求关闭,通常在数据传输阶段使用。 -
SEQ:序列号,这个序列号初始值是随机的,但是在过程中是不断增加的。
-
TCP的三次握手
概述:三次握手是TCP协议在建立连接进行数据传输的机制,确保客户端和服务端双方都同意建立连接,并初始化序列号以实现可靠的数据传输。这个过程涉及三个步骤:SYN、SYN-ACK和ACK。通过这个握手,TCP 可以防止旧的重复连接初始化问题,并确保连接是双向的。步骤1:客户端发起同步请求
作用:客户端发送SYN ,附带自己的初始序列号(SEQ,例如 client_isn)。这个包不携带数据,只是请求连接。
目的:告诉服务器“我想连接你,并告诉你我的起始序列号”。
状态变化:客户端进入SYN_SENT状态,等待服务器响应。(如果服务器未响应客户端会重试或者超时)
标识变化:SYN=1,ACK=0。SYN标识位为1(SYN=1)表示请求连接,ACK标识为0(ACK=0)表示当前没有什么确认的可以忽略,在初次连接的时候。步骤2:服务器响应并确认
作用:服务器收到客户端的 SYN 后,如果同意连接,就发送 SYN-ACK :附带自己的初始序列号(SEQ,例如server_isn),确认客户端的序列号,ACK 值设为 client_isn+1,表示已收到并期待下一个字节。
目的:服务器一方面确认了客户端的请求(ACK),另一方面也请求客户端同步自己的序列号(SYN)。这确保连接是双向的。
状态变化:服务器进入SYN_RCVD状态。
标识变化:SYN=1,ACK=1。SYN标识位为1(SYN=1)表示请求连接,ACK标识为1(ACK=1)表示确认客户端的SYN 附带的初始化序列号。步骤3:客户端确认
作用:客户端收到了服务器的SYN_ACK后发送ACK,ACK值设为server_isn+1,确定服务器的序列号。
目的:告诉服务器,你的同步请求已收到,连接可以开始了。此时连接正式建立双方进入ESTABLISHED状态,可以传输数据。
状态变化:客户端进入 ESTABLISHED(已建立) 状态;服务器收到 ACK 后也进入 ESTABLISHED 状态。连接正式建立,数据传输可以开始。
标识变化:SYN=0,ACK=1。SYN标识位为0(SYN=0)当前已经连接完成不需要SYN,ACK标识为1(ACK=1)表示收到了服务端的确认。PS:ACK与SEQ的关系:ACK值总是等于对方SEQ + 1(或 + 数据长度),表示“我已收到这些字节,期待下一个”。如果没有SEQ,数据可能会乱序、丢失,无法重传或确认。

为什么是三次握手,而不是两次或者四次?
两次握手不足,如果只有第一次的SYN和最后一次的ACK,服务器是无法确认客户端是否收到了它的ACK,导致潜在的半连接问题。
四次握手多余,三次已经足够确认双方同步和确认,避免不必要的开销。
-
TCP的四次挥手
概述:四次挥手是TCP协议在关闭连接时使用的机制,它确保双方有序的结束数据传输,避免数据丢失或残留链接。这个过程涉及四个步骤FIN、ACK、FIN、ACK。通过这个挥手,TCP 可以处理半关闭状态(half-close),允许一方先关闭发送通道,而另一方可能还有数据要发。步骤 1: 客户端发起结束请求
作用:发送FIN请求结束发送数据,附带自己的累计后的序列号(SEQ,例如client_nxt)
目的:客户端通知服务器“我没有更多数据要发了,但你可以继续发数据给我”(半关闭)。
状态变化:客户端进入 FIN_WAIT_1 状态,等待服务器确认。
标识变化:FIN=1,ACK=1。FIN标识位为1(FIN=1)客户端请求关闭发送通道,ACK标识为1(ACK=1)连接建立后通常为1。步骤 2: 服务器确认客户端的结束请求
作用:服务器收到 客户端的结束请求(FIN)后,发送一个 ACK确认客户端的序列号,ACK 值设为 client_nxt+1,表示已收到并期待下一个字节。(确认收到客户端的 FIN)。
目的:服务器确认“我知道你不发了,但我可能还有数据要发给你”。此时,服务器可以继续发送剩余数据。
状态变化:服务器进入 CLOSE_WAIT 状态;客户端收到 ACK 后进入 FIN_WAIT_2 状态(等待服务器的 FIN)。
标识变化:FIN=0,ACK=1。FIN标识位为0(FIN=0)这次是服务器应答客户端的所以FIN标识为0,ACK标识为1(ACK=1)表示服务器确认客户端关闭。
为什么单独 ACK:这允许服务器处理剩余数据。如果立即发 FIN,会丢失半关闭的机会。步骤 3: 服务器发起结束请求
作用:服务器发送完所有数据后,发送 FIN ,附带自己累计后的序列号(SEQ,例如server_nxt)。
目的:服务器通知客户端“我也没有数据要发了,准备关闭”。
状态变化:服务器进入 LAST_ACK 状态,等待最终确认。
标识变化:FIN=1,ACK=1。FIN标识位为1(FIN=1)这次是服务端要进行关闭所以FIN标识为1,ACK标识为1(ACK=1)连接建立后通常为1。步骤 4: ACK(客户端确认服务器的 FIN)
作用:客户端收到服务器的 FIN 后,发送 ACK确认服务器的序列号,ACK值设为server_nxt+1。
目的:客户端确认“好的,你也结束了,连接关闭”。
状态变化:客户端进入 TIME_WAIT 状态(等待 2MSL,通常 2-4 分钟,以处理延迟包);服务器收到 ACK 后进入 CLOSED 状态。客户端超时后也进入 CLOSED。
标识变化:FIN=0,ACK=1。FIN标识位为0(FIN=0)这次客户端应答服务器的关闭所以FIN标识为0,ACK标识为1(ACK=1)表示客户端确认服务端关闭。
注意:TIME_WAIT 防止旧包干扰新连接。

为什么是四次挥手,而不是三次?
三次不足:关闭需要处理半关闭(一方先关),如果合并第二个和第三个步骤,服务器无法发送剩余数据,导致数据丢失。
四次必要:它分离了双方的关闭请求,确保有序结束。实际中,第二个和第三个步骤有时合并(piggyback FIN on ACK),但标准是四次。
对比三次握手:握手是同步建立,四次挥手是异步关闭。
TCP粘包/拆包的概念
粘包:发送方发送了两条消息,接收方一次read()可能把两条消息读成一条。
发送方: |消息1| |消息2|
接收方 read(): |消息1消息2|
拆包:发送方发送一条消息,接收方一次read()只接受了部分数据。
发送方: |消息1|
接收方 read(): |消息1的前半部分|
原因:
TCP 是 流式传输,没有消息边界。
内核发送缓冲区可能合并多次写操作。
接收缓冲区可能只读到部分数据。
网络状况、Nagle 算法等因素也可能导致粘包/拆包。
解决思路:
在应用层实现消息边界,最常见的方式设置长度前缀。
在每条消息前面加上长度,接收端先读长度,在读消息体。
比方设计前四个字节是代表消息长度。
四、UDP
UDP 是一种无连接、面向报文(datagram)、不保证可靠性的传输层协议,优点是开销小、延迟低、支持广播/组播,适合实时或短报文场景。
-
协议定位与作用
层级:传输层(OSI 第4层 / TCP/IP 传输层)。
作用:把上层应用的数据封装成独立的数据报,通过 IP 发送到目标主机 + 端口,提供端到端“尽力而为”的传输服务。
与 TCP 的根本区别:UDP 不建立连接、不确认、不重传、不保证顺序。 -
工作机制
发送方
将数据封装为UDP报文(加上8字节头部)。
不建立连接,直接发送给目标IP+端口。
接收方
通过端口接收。
若报文丢失、重复或乱序,UDP 不做任何处理,交由应用层决定。 -
UDP 的核心特性(对比 TCP)
无连接:不需要建立或拆除连接。
不可靠:协议不重传、不确认——丢包、重复、乱序都可能发生,应用层需自处理。
低开销、低延迟:头小(8B)、处理快,适合实时应用。
支持广播/组播:可发送到广播地址或组播组(多点分发),TCP 不支持。

6834

被折叠的 条评论
为什么被折叠?



