当前位置: 首页 > news >正文

计算机网络】深入解析 TCP 协议:从三次握手到拥塞控制

文章目录

  • 一、TCP 协议概述
  • 二、TCP 连接建立:三次握手(Three-Way Handshake)
    • 1. 过程解析
    • 2. 为什么是三次?
  • 三、TCP 连接释放:四次挥手(Four-Way Handshake)
    • 1. 过程解析
    • 2. TIME_WAIT 状态的作用
  • 四、TCP 可靠传输机制(扩展版)
    • 1. 滑动窗口(Sliding Window)
    • 2. 拥塞控制(代码实现)
  • 五、TCP 状态机与关键状态(扩展版)
    • 1. 状态机详解
  • 六、半连接与全连接队列(扩展版)
    • 1. Linux 系统调优
    • 2. SYN Flood 攻击防御代码
  • 七、字节流与序列号(扩展版)
    • 1. 粘包问题解决方案
  • 八、TCP 优化与常见问题(扩展版)
    • 1. Nagle 算法与延迟确认
    • 2. TIME_WAIT 优化
  • 九、TCP 编程实战(新增章节)
    • 1. Python 实现 TCP 服务器与客户端
    • 2. 多线程与异步 TCP 服务器对比
  • 十、TCP 性能调优实战(新增章节)
    • 1. Linux 系统参数优化清单
    • 2. 网络抓包分析(Wireshark)
  • 十一、TCP 面试高频问题
    • 为什么 TCP 连接是三次握手,而关闭是四次挥手?
    • TIME_WAIT 状态存在的意义?
    • 如何排查 TCP 连接超时问题?
    • TCP 和 UDP 的本质区别?
  • 十二、总结

一、TCP 协议概述

TCP(Transmission ControlProtocol)是传输层的面向连接、可靠的字节流协议,通过三次握手建立连接,四次挥手释放连接,利用滑动窗口、拥塞控制等机制保证数据可靠传输,适用于对可靠性要求高的场景(如HTTP、FTP)。

二、TCP 连接建立:三次握手(Three-Way Handshake)

1. 过程解析

第一次握手(SYN):客户端发送 SYN 包(SEQ=x),进入 SYN_SENT 状态。
第二次握手(SYN+ACK):服务端回复 SYN(SEQ=y)和 ACK(ACK=x+1),进入 SYN_RCVD 状态。
第三次握手(ACK):客户端回复 ACK(ACK=y+1),双方进入 ESTABLISHED 状态。

2. 为什么是三次?

双向确认:确保双方收发能力正常。若仅两次握手,服务端无法验证客户端是否收到 ACK(旧连接残留的 SYN 包可能导致误连)。三次握手通过双向确认,避免无效连接。

三、TCP 连接释放:四次挥手(Four-Way Handshake)

1. 过程解析

第一次挥手(FIN):主动关闭方发送 FIN(SEQ=u),进入 FIN_WAIT_1。
第二次挥手(ACK):被动关闭方回复 ACK(ACK=u+1),进入 CLOSE_WAIT;主动关闭方进入 FIN_WAIT_2。
第三次挥手(FIN):被动关闭方发送 FIN(SEQ=v),进入 LAST_ACK。
第四次挥手(ACK):主动关闭方回复 ACK(ACK=v+1),进入 TIME_WAIT(等待 2MSL 后关闭);被动关闭方收到 ACK 后关闭。

2. TIME_WAIT 状态的作用

确保 ACK 可靠:若最后一个 ACK 丢失,被动关闭方会重发 FIN,TIME_WAIT 期间可重传 ACK。
避免旧连接干扰:2MSL(报文最大生存时间)确保网络中残留的旧报文过期,不影响新连接。

四、TCP 可靠传输机制(扩展版)

1. 滑动窗口(Sliding Window)

窗口动态调整示例:
发送方窗口大小 = min (拥塞窗口,接收窗口)

// 发送方视角:窗口随ACK动态变化
已发送未确认:[1000-1999] // 已发送SEQ=1000-1999的数据包
可发送未发送:[2000-2999] // 窗口大小=2000字节,接收方允许发送 未发送:[3000-∞] // 超出当前窗口范围

代码模拟滑动窗口:

class SlidingWindow:def __init__(self, window_size):self.window_size = window_size  # 窗口大小self.base = 0                   # 已发送未确认的第一个字节self.next_seq = 0               # 下一个待发送的字节def can_send(self, seq):return seq < self.base + self.window_sizedef receive_ack(self, ack):if ack > self.base:self.base = ack  # 窗口滑动# 触发窗口内未发送数据的发送

2. 拥塞控制(代码实现)

Python 模拟拥塞控制算法:

class CongestionControl:def __init__(self):self.cwnd = 1         # 初始拥塞窗口self.ssthresh = 65535 # 慢启动阈值def slow_start(self):if self.cwnd < self.ssthresh:self.cwnd += 1    # 指数增长else:self.congestion_avoidance()def congestion_avoidance(self):self.cwnd += 1/self.cwnd  # 线性增长def handle_loss(self):self.ssthresh = max(2, self.cwnd/2)self.cwnd = 1           # 发生丢包,重置窗口

五、TCP 状态机与关键状态(扩展版)

1. 状态机详解

TCP 状态转移图: 客户端: CLOSED → SYN_SENT → ESTABLISHED → FIN_WAIT_1 →
FIN_WAIT_2 → TIME_WAIT → CLOSED 服务端: CLOSED → LISTEN → SYN_RCVD →
ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED

关键状态代码示例:

# 模拟TCP状态机(简化版)
class TCPStateMachine:def __init__(self):self.state = "CLOSED"def process_event(self, event):if self.state == "CLOSED":if event == "主动打开":self.state = "SYN_SENT"# 发送SYN包elif self.state == "SYN_SENT":if event == "收到SYN+ACK":self.state = "ESTABLISHED"# 发送ACK包# 其他状态转移...

六、半连接与全连接队列(扩展版)

1. Linux 系统调优

查看和调整队列大小:

# 查看半连接队列大小
sysctl net.ipv4.tcp_max_syn_backlog  # 默认值通常为128# 查看全连接队列大小上限
sysctl net.core.somaxconn            # 默认值通常为128# 临时调整(重启失效)
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
sysctl -w net.core.somaxconn=4096# 永久调整:修改/etc/sysctl.conf后执行sysctl -p
net.ipv4.tcp_max_syn_backlog = 4096
net.core.somaxconn = 4096

2. SYN Flood 攻击防御代码

Python 模拟 SYN Cookies 生成
import time
import hashlibdef generate_syn_cookie(ip, port, timestamp):# 实际实现更复杂,包含秘密值和时间戳secret = "server_secret_key"data = f"{ip}{port}{timestamp}{secret}"return hashlib.md5(data.encode()).hexdigest()[:8]

七、字节流与序列号(扩展版)

1. 粘包问题解决方案

定长协议实现:
import structdef send_fixed_length(sock, data, length=1024):# 填充或截断数据到固定长度data = data.ljust(length, b'\x00')sock.sendall(data)def recv_fixed_length(sock, length=1024):data = b''while len(data) < length:chunk = sock.recv(length - len(data))if not chunk:breakdata += chunkreturn data

长度前缀协议实现:

def send_with_length(sock, data):# 先发送4字节的长度信息length = len(data)sock.sendall(struct.pack('!I', length))sock.sendall(data)def recv_with_length(sock):# 先接收4字节的长度信息length_data = sock.recv(4)if len(length_data) < 4:return Nonelength = struct.unpack('!I', length_data)[0]# 再接收指定长度的数据data = b''while len(data) < length:chunk = sock.recv(length - len(data))if not chunk:breakdata += chunkreturn data

八、TCP 优化与常见问题(扩展版)

1. Nagle 算法与延迟确认

Python socket 禁用 Nagle 算法:

import sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)  # 禁用Nagl

延迟确认示例:

2. TIME_WAIT 优化

调整 Linux 系统参数:

# 启用TIME_WAIT状态重用
sysctl -w net.ipv4.tcp_tw_reuse=1# 缩短TIME_WAIT超时时间(默认2MSL=120秒)
sysctl -w net.ipv4.tcp_fin_timeout=30

九、TCP 编程实战(新增章节)

1. Python 实现 TCP 服务器与客户端

# TCP服务器示例
import socket
import threadingdef handle_client(client_socket):try:while True:data = client_socket.recv(1024)if not data:breakclient_socket.sendall(b"Server received: " + data)finally:client_socket.close()server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8888))
server.listen(5)  # 全连接队列大小print("Server listening on port 8888...")
while True:client, addr = server.accept()print(f"Accepted connection from {addr}")client_handler = threading.Thread(target=handle_client, args=(client,))client_handler.start()
# TCP客户端示例
import socketclient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 8888))try:client.sendall(b"Hello, server!")response = client.recv(1024)print(f"Received from server: {response.decode()}")
finally:client.close()

2. 多线程与异步 TCP 服务器对比

多线程服务器(阻塞 IO):
优点:实现简单;缺点:线程开销大,连接数受限于线程数量。
异步服务器(非阻塞 IO):

# 使用asyncio实现异步TCP服务器
import asyncioasync def handle_echo(reader, writer):data = await reader.read(1024)writer.write(b"Async server received: " + data)await writer.drain()writer.close()async def main():server = await asyncio.start_server(handle_echo, 'localhost', 8888)async with server:await server.serve_forever()asyncio.run(main())

十、TCP 性能调优实战(新增章节)

1. Linux 系统参数优化清单

# 增大TCP接收/发送缓冲区
sysctl -w net.ipv4.tcp_rmem="4096 87380 67108864"  # 最小、默认、最大接收窗口
sysctl -w net.ipv4.tcp_wmem="4096 65536 67108864"  # 最小、默认、最大发送窗口# 启用TCP窗口缩放(RFC 1323)
sysctl -w net.ipv4.tcp_window_scaling=1# 启用TCP时间戳(用于PAWS和RTT计算)
sysctl -w net.ipv4.tcp_timestamps=1# 优化TCP重传策略
sysctl -w net.ipv4.tcp_syn_retries=3       # SYN发送重试次数
sysctl -w net.ipv4.tcp_retries2=8          # 数据段重传次数

2. 网络抓包分析(Wireshark)

过滤表达式示例: tcp.port == 80 # 过滤TCP 80端口 tcp.flags.syn
== 1 and tcp.flags.ack == 0 # 过滤SYN包 tcp.analysis.retransmission # 过滤重传包

十一、TCP 面试高频问题

为什么 TCP 连接是三次握手,而关闭是四次挥手?

答:建立连接时,服务端的 SYN 和 ACK 可合并发送;关闭时,被动方可能需延迟发送 FIN(如等待数据处理完毕),因此需四次。

TIME_WAIT 状态存在的意义?

答:
确保最后一个 ACK 可靠到达(若丢失,被动方会重发 FIN)。
避免旧连接的延迟报文影响新连接(等待 2MSL 确保所有旧报文过期)。

如何排查 TCP 连接超时问题?

答:
检查防火墙规则(是否拦截 SYN 包)。
使用 netstat -s 查看 TCP 统计信息(如 SYN_RECV 队列溢出)。
Wireshark 抓包分析(是否存在 SYN 包无响应)。

TCP 和 UDP 的本质区别?

答:TCP 提供可靠、面向连接、有序的字节流服务;UDP 提供无连接、不可靠、快速的数据报服务。选择取决于应用场景(如 HTTP 需 TCP,实时游戏可用 UDP)。

十二、总结

TCP 协议通过精巧的设计(三次握手、滑动窗口、拥塞控制等),在不可靠的网络层上构建了可靠的传输服务。理解其原理不仅能解决网络故障(如连接超时、丢包),还能指导高性能网络应用开发(如优化服务器参数、设计高效协议)。

在实际工作中,需根据业务场景权衡 TCP 与 UDP 的选择,并针对具体问题(如粘包、TIME_WAIT 堆积)设计解决方案。掌握 TCP 协议,是成为优秀后端工程师、网络工程师的必备技能。

http://www.xdnf.cn/news/648865.html

相关文章:

  • java高级 -动态代理
  • 华为云Flexus+DeepSeek征文 | DeepSeek-V3/R1商用服务开通体验全流程及使用评测
  • 项目部署一次记录
  • 第7章:Zephyr 的低功耗机制
  • 在 ElementUI 中实现 Table 单元格合并
  • 【Android】SharePreference原理
  • 【ARTS】【LeetCode-59】螺旋矩阵
  • 【HarmonyOS 5应用架构详解】深入理解应用程序包与多Module设计机制
  • 深度解析 8086 处理器:x86 架构的奠基者
  • 【后端高阶面经:架构篇】46、分布式架构:如何应对高并发的用户请求
  • 2025社区团购系统开发:未来趋势、核心技术与落地解决方案
  • Python - 文件部分
  • 【React】- React-RND 深度使用指南:实现自由拖拽、避坑受控陷阱!
  • Hadoop架构与核心模块解析
  • 【每日渲美学】3ds Max橱柜材质教程:厨房高光烤漆、木纹、亚克力、亚光板材渲染优化指南
  • 洪水危险性评价与风险防控全攻略:从HEC-RAS数值模拟到ArcGIS水文分析,一键式自动化工具实战,助力防洪减灾与应急管理
  • 探索数据结构之顺序表:从入门到精通
  • 「读书报告」Spark实时大数据分析
  • 数据结构-图的应用,实现环形校验和拓扑排序
  • redis五种数据结构详解(java实现对应的案例)
  • 高阶数据结构——哈希表的实现
  • Elasticsearch 节点角色详解及协调节点请求策略
  • FFmpeg 4.3 H265 二十二.2,在网络环境RTSP中,断线下如何处理
  • Oracle NLS_LANG 常见问题
  • sqli-labs第二十八关——Trick with ‘union select‘
  • Flink Checkpoint SavePoint 深度剖析与工程实践
  • 在Spring Boot中实现Kafka动态反序列化:针对多主题的灵活数据处理
  • 网络安全-等级保护(等保) 3-2-2 GB/T 28449-2019 第7章 现场测评活动/第8章 报告编制活动
  • JVM GC 分类与原理深度解析
  • 10:图像传参+UI界面互传