news 2026/9/8 7:28:41

TCP与UDP深度对比:从三次握手到抓包排错,一文读懂传输层协议

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TCP与UDP深度对比:从三次握手到抓包排错,一文读懂传输层协议

TCP 和 UDP 是计算机网络里最基础的一对传输层协议。很多开发者背过“TCP 面向连接、可靠、慢;UDP 无连接、不可靠、快”的口诀,但一到实际定位问题就发懵:为什么bind: only one usage of each socket address?为什么curl: (35) tcp connection reset by peer?为什么 UDP 测试工具收不到包,Wireshark 却显示数据已经发出去了?这篇文章会把 TCP 与 UDP 的机制、报文、适用场景、调试工具、常见报错逐个拆开讲清楚。

先说核心结论:TCP 是传输控制协议,适合对数据完整性要求极高的业务;UDP 是用户数据报协议,适合低延迟、可容忍少量丢包的业务。现实中很多服务协议,比如 HTTP/HTTPS、WebSocket、Modbus TCP、SSH 走的是 TCP;而视频直播、语音通话、实时游戏同步、SNMP、组播经常走 UDP。下面从能力对比、协议机制、实际验证、排错方法四个维度展开。

1. TCP 与 UDP 核心能力速览

对比项TCPUDP
全称Transmission Control ProtocolUser Datagram Protocol
连接状态面向连接,需要三次握手建立连接、四次挥手释放连接无连接,发送前不需要建立连接
可靠性可靠传输,支持确认、重传、去重、按序到达不可靠,不保证送达、不保证顺序、不保证不丢包
数据边界字节流,无边界,应用层需要自定义分包规则数据报,每个报文独立,有明确边界
流量控制支持滑动窗口流量控制不支持
拥塞控制支持慢启动、拥塞避免、快速重传不支持
广播/组播不支持一对多传输支持一对多、多对多
头部开销20 字节及以上,带选项时更大固定 8 字节
传输效率较低,受确认、重传、拥塞控制影响较高,没有确认机制,延迟低
连接数量高并发时服务端需要维护大量连接状态服务端无需维护连接状态,因此可扩展性更高
典型应用HTTP、HTTPS、SSH、WebSocket、Modbus TCP、数据库连接DNS 查询、DHCP、TFTP、SNMP、RTSP 实时流、游戏同步、VoIP
系统资源占用高,每个连接都有状态内存、收发缓冲区低,无连接状态,仅需要绑定端口
编程复杂度高,要处理粘包、拆包、断线重连、心跳保活低,直接发送报文,但业务层要自己处理可靠性

这张表可以快速作为选型依据:如果业务要求“丢一个字节都不能接受”,选 TCP;如果业务要求“延迟要低,丢少量数据可以接受”,选 UDP。

2. TCP 工作机制:连接、确认与状态机

2.1 TCP 三次握手

TCP 建立连接的过程是三次握手,目的是让通信双方确认彼此的收发能力,并同步初始序列号。

过程如下:

  1. 客户端发送SYN=1, seq=x报文,进入SYN_SENT状态。
  2. 服务端收到后回复SYN=1, ACK=1, seq=y, ack=x+1,进入SYN_RCVD状态。
  3. 客户端发送ACK=1, seq=x+1, ack=y+1,双方进入ESTABLISHED状态。

用文本时序表示:

客户端 服务端 |------- SYN seq=x --------->| |<-- SYN+ACK seq=y, ack=x+1 --| |------- ACK seq=x+1 -------->| | 连接建立成功 |

如果只握手两次,服务端无法确认客户端的接收能力是否正常;握手四次则多余,所以三次是完备方案。

2.2 TCP 四次挥手

断开连接时使用四次挥手,因为 TCP 是全双工连接,每个方向的关闭必须独立确认。

过程如下:

  1. 主动关闭方发送FIN,表示不再发送数据,进入FIN_WAIT_1
  2. 被动关闭方回复ACK,进入CLOSE_WAIT;此时被动方仍然可以发送数据。
  3. 被动关闭方数据发送完毕后,发送FIN,进入LAST_ACK
  4. 主动关闭方回复ACK,进入TIME_WAIT,等待一段时间后关闭。
主动关闭方 被动关闭方 |------- FIN ---------------->| |<------- ACK ----------------| | | |<------- FIN ----------------| |------- ACK ---------------->| | |

这里经常会被问到:为什么主动关闭方要停留在TIME_WAIT?因为最后一个 ACK 可能丢失,如果被动方没有收到 ACK,它会重发 FIN,主动方必须保留足够时间处理重发的 FIN。同时,TIME_WAIT能防止旧的连接报文影响新连接。

线上经常会出现大量TIME_WAIT连接,一般不需要过度优化。如果机器短时间内产生上万条TIME_WAIT,可以先排查是否短连接创建过于频繁,再考虑调整系统参数。

2.3 TCP 状态机速查

排查连接问题经常要用netstatss查看连接状态。常见状态含义如下:

状态含义
LISTEN服务端正在监听端口
SYN_SENT客户端发送 SYN 后等待服务端回应
SYN_RCVD服务端收到 SYN 并回复 SYN+ACK,等待客户端 ACK
ESTABLISHED连接建立成功,正在进行数据传输
FIN_WAIT_1主动关闭方发送 FIN,等待 ACK
FIN_WAIT_2主动关闭方已收到 ACK,等待被动方 FIN
CLOSE_WAIT被动关闭方收到 FIN,回复 ACK 后等待本地应用关闭连接
LAST_ACK被动关闭方发送 FIN,等待主动方 ACK
TIME_WAIT主动关闭方收到 FIN 并回复 ACK,等待足够时间确保对端收到

排查时,如果服务端出现大量CLOSE_WAIT,通常是应用程序没有正确调用close()或连接未释放;出现大量TIME_WAIT,则常见于短链接服务,一般通过长连接或连接池优化。

3. UDP 工作机制:无连接、有边界、不保证送达

UDP 的核心特点是简单。发送端只要指定目的 IP 和端口,内核把数据报封装后直接丢到网络上,不需要握手,不需要确认,也不需要维护连接状态。

因为 UDP 没有确认和重传,所以丢包之后发送端无感知。接收端收到报文时,每个报文都是独立的,不会像 TCP 那样合并成字节流,因此 UDP 天然保留数据报边界。举个例子,如果发送端连续发送 3 个 UDP 报文,接收端调用recvfrom()三次,每次读到的是一个完整的原始报文,不会出现 TCP 的粘包拆包问题。这一点是很多入门开发者最容易混淆的地方。

但也正因为没有连接状态,UDP 也带来一些容易踩坑的问题:

  • 没有拥塞控制,网络拥塞时 UDP 报文会被直接丢弃,视频、音频会出现卡顿或花屏。
  • 没有传输层去重机制,应用层可能收到重复报文。
  • 没有传输层分片重组之外的顺序保证,网络路径变化会导致报文乱序。
  • 数据报长度受限:IPv4 下 UDP 报文最大长度理论上是 65507 字节,但实际链路 MTU 通常限制为 1500 字节,如果应用层发送过大报文,IP 层会分片,分片报文一旦有一片丢失,整个数据报都会被丢弃。

简单总结:UDP 的“不可靠”是协议层不保证可靠,不是网络环境雪崩的外在表现。开发者如果想在 UDP 上获得可靠传输,需要在应用层自己实现确认、重传、排序、去重逻辑,或者直接使用 KCP、QUIC 这类基于 UDP 改造的可靠协议。

4. TCP 与 UDP 报文结构对比

4.1 TCP 报文头

TCP 头部最少 20 字节,结构如下:

  • 源端口(16 bit)
  • 目的端口(16 bit)
  • 序号(32 bit)
  • 确认序号(32 bit)
  • 数据偏移(4 bit)
  • 保留(3 bit)
  • 标志位(9 bit),包括 URG、ACK、PSH、RST、SYN、FIN 等
  • 窗口大小(16 bit)
  • 校验和(16 bit)
  • 紧急指针(16 bit)
  • 选项字段(可变)

SYNFINRST这几个标志位在实际排错中很重要:

  • SYN:建立连接请求。
  • FIN:正常关闭连接。
  • RST:异常中断连接。比如服务端没有监听对应端口,客户端连接时可能收到RST;应用程序主动 Reset 连接,也会收到RST

报文里的序号机制保证了字节流可以按序重组,这也是 TCP 可靠性的一个重要基础。

4.2 UDP 报文头

UDP 头部只有 8 字节:

  • 源端口(16 bit)
  • 目的端口(16 bit)
  • 长度(16 bit),表示 UDP 头部和数据的总长度
  • 校验和(16 bit)

头部足够简单,所以协议开销远小于 TCP。没有序号,没有确认序号,没有标志位,没有窗口。传输层能提供的信息非常有限,端口之外,剩下的可靠性完全交给网络环境和应用自身。

在 Wireshark 抓包时,TCP 报文可以直接看到 [SYN]、[ACK]、[FIN]、[RST] 等标记,也方便跟踪流;UDP 报文通常就一行源端口、目的端口和长度,内容要么放在 payload 里,要么配合 RTSP、SNMP 等协议解析。

5. 可靠传输、流量控制与拥塞控制

很多人只知道“TCP 可靠”,但不知道它靠什么机制可靠。TCP 的可靠性由几个机制叠加完成:

  1. 确认机制:接收方收到数据后返回 ACK。
  2. 超时重传:发送方如果长时间未收到 ACK,会重新发送数据。
  3. 去重:接收方根据序号去重,同一个数据即使多次收到也只保留一份。
  4. 按序重组:序号让接收方可以把乱序到达的报文重新排好。
  5. 校验和:接收方校验数据完整性,出错则丢弃并等待重传。

流量控制方面,TCP 使用滑动窗口机制。接收方会告诉发送方“我的接收窗口还剩多少”,发送方根据窗口大小决定一次性发送多少数据。这样能避免发送方过快导致接收方缓冲区溢出。

拥塞控制方面,TCP 有慢启动、拥塞避免、快速重传、快速恢复等策略。刚建立连接时,发送方不会一次性把大量数据打到网络上,而是从较小拥塞窗口开始,逐步增大窗口;出现丢包或超时后,主动降低发送速度。这种机制保证了网络的稳定性,但也造成了高 RTT 场景下的传输延迟。

UDP 则完全没有这些控制机制。它能做多少发送、发送多快,完全由应用自己控制。很多实时音视频方案选择 UDP,是因为实时性优先,宁可丢几帧,也不愿意等待重传造成延迟。

6. TCP 与 UDP 实际应用场景

选择 TCP 还是 UDP,最终取决于业务对“可靠”和“低延迟”的取舍。

6.1 适合 TCP 的场景

  • HTTP/HTTPS:网页请求、接口调用,数据不能丢。
  • WebSocket:实时推送、在线聊天、协作编辑,底层走 TCP。
  • SSH:远程终端操作,命令传输和回显必须可靠。
  • FTP/SFTP:文件传输,损坏一个字节都不可接受。
  • 数据库连接:MySQL、Redis 客户端等,持久连接场景,需要可靠传输。
  • Modbus TCP:工业现场 PLC 通信,使用 TCP 承载 Modbus 协议,依靠 TCP 保证请求响应可靠性。
  • 邮件服务 SMTP/IMAP:内容完整性和顺序性优先。
  • 消息队列:Kafka、RocketMQ 等内部通信,以及对 ACK 有依赖的业务,通常基于 TCP。

6.2 适合 UDP 的场景

  • DNS 查询:域名解析请求通常用 UDP 报文完成,请求量小、响应快;域名响应过大时才会切换为 TCP。
  • DHCP:客户端在无 IP 环境下用广播发送 DHCP 请求,必须走 UDP。
  • TFTP:简单文件传输协议,用于网络设备固件升级等轻量场景。
  • SNMP:网络设备监控,走 UDP 161/162 端口。
  • 实时音视频直播:RTP/RTSP 的实时流媒体,接收方可以容忍少量丢包,但延迟必须低。
  • 在线游戏:位置同步、移动操作等状态上报,要求低延迟,少量丢包不会造成致命问题。
  • 组播/广播:UDP 天然支持一对多传输,适合局域网设备发现、服务发现场景。
  • 物联网设备:很多嵌入式设备上报传感器数据使用 UDP,设备资源受限,协议越简单越好。

6.3 两个典型对比

  • WebSocket 与 UDP:WebSocket 的底层是 TCP,它提供的是应用层的全双工通信通道;如果业务要求低延迟,并且允许丢包,可以考虑基于 UDP 的私有协议或 QUIC。
  • Modbus TCP 与 RTU:Modbus 本身定义的 TCP 端口是 502,通信依赖于 TCP 的可靠字节流;但如果工业场景需要 PLC 与海康相机等设备快速同步状态,也可以选择 UDP 通道,但一定要在应用层做超时和重试。

7. 本地环境下的 TCP 与 UDP 实验验证

理论看完,可以在本机做一组实验,直接感受 TCP 和 UDP 的区别。下面提供三个可以直接运行的验证方案:使用nc工具、使用 Python socket、使用 Wireshark 抓包。

7.1 安装工具

在 Linux 上安装netcat-openbsdiperf3

sudo apt update sudo apt install -y netcat-openbsd iperf3

在 Windows 上,可以使用 PowerShell 自带的Test-NetConnection来测试 TCP 连通性,UDP 测试可以用第三方工具或 Python socket。

7.2 TCP 回环测试

启动一个 TCP 服务端:

# 终端 A nc -l 127.0.0.1 8888

连接并发送数据:

# 终端 B nc 127.0.0.1 8888 hello tcp

在终端 A 能看到hello tcp。如果服务端没有启动,客户端会收到类似Connection refused的报错,这就是 TCP 的连接机制起作用了。

7.3 UDP 回环测试

启动一个 UDP 服务端:

# 终端 A nc -u -l 127.0.0.1 9999

发送数据:

# 终端 B nc -u 127.0.0.1 9999 hello udp

在终端 A 可以收到hello udp。如果把终端 A 关掉,终端 B 发送数据时通常不会立即报错,因为 UDP 是无连接的,发送端并不知道接收端是否在监听。

7.4 用 Python 写一个 TCP 回声服务

下面这个例子演示 TCP 服务端需要循环等待连接,并且每个连接单独处理数据:

import socket server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('127.0.0.1', 8888)) server.listen(5) print('TCP server listening on 127.0.0.1:8888') while True: conn, addr = server.accept() print(f'client connected: {addr}') with conn: while True: data = conn.recv(1024) if not data: break conn.sendall(b'echo: ' + data)

用一行命令测试:

printf 'hello tcp\n' | nc 127.0.0.1 8888

输出:

echo: hello tcp

7.5 用 Python 写一个 UDP 回声服务

UDP 服务端没有accept(),只有一个 socket 反复接收数据:

import socket server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.bind(('127.0.0.1', 9999)) print('UDP server listening on 127.0.0.1:9999') while True: data, addr = server.recvfrom(1024) print(f'client: {addr}, data: {data}') server.sendto(b'echo: ' + data, addr)

测试:

printf 'hello udp\n' | nc -u -w1 127.0.0.1 9999

注意,这里nc会立即发送数据并退出,UDP 服务端打印一次接收日志就算验证成功。

两个示例的服务端代码虽然都叫“回声服务”,但编程模型完全不同。TCP 多了一个连接维护的过程,UDP 则更接近“收包-回包”的简单循环。

8. 使用 Wireshark 抓包验证三次握手

如果没有抓包经验,可以先用loopback接口抓本机数据。打开 Wireshark,选择 Loopback 接口,然后在终端执行:

nc 127.0.0.1 8888

输入任意内容后关闭连接。在 Wireshark 过滤栏输入tcp.port == 8888,可以看到三次握手的SYNSYN+ACKACK报文,以及结束时的FINACK报文。这个过滤条件适合验证端口号是否生效。

如果过滤栏输入udp.port == 9999,同样能看到 UDP 单次发送的报文。Wireshark 里面 UDP 的报文非常干净,没有握手,没有确认,一眼就能看出两种协议的区别。

这里补充一个常见困惑:为什么 Wireshark 设置了 UDP 过滤条件udp,但还是抓到 ICMP 报文?因为 Wireshark 的捕获过滤器(capture filter)和显示过滤器(display filter)是两套语法。如果使用抓包工具默认设置,实际上只在“显示”层面做了过滤,网卡物理收到的所有报文仍然进内存。要在捕获阶段就过滤,需要使用udp的 capture filter 语法,或者在显示过滤器中明确限制为udp且不包含其他协议。

9. 基于 iperf3 的性能测试

iperf3 是常用的网络性能测试工具,支持 TCP 和 UDP 两种模式。

9.1 启动 iperf3 服务端

iperf3 -s

默认监听 5201 端口。如果要测试指定端口:

iperf3 -s -p 5202

9.2 TCP 带宽测试

客户端执行:

iperf3 -c 127.0.0.1 -p 5201 -t 10

这里-t 10表示测试 10 秒。回显结果中会包含传输数据量、带宽、重传次数。TCP 测试重点关注重传次数,重传过高说明链路质量较差或拥塞控制触发频繁。

9.3 UDP 带宽与丢包测试

客户端执行 UDP 模式时,需要指定带宽上限:

iperf3 -c 127.0.0.1 -u -b 100M -t 10

-u表示 UDP 模式,-b 100M表示以 100 Mbps 速率发送。回显中会包含Loss丢包率、抖动Jitter和每秒报文数。

UDP 测试结果需要区分发送端和接收端的统计。iperf3 输出中通常会显示本地发送段和远端接收段。如果只关心发送端是否成功发出,看 sender 统计;如果关心网络传输质量,看 receiver 统计。很多人在调 UDP 时只看了发送端没有报错,就以为没有丢包,这是明显的误区。

9.4 观察端口连接状态

测试时可以在另一个终端执行:

ss -tnp | grep 5201

Linux 下可以用ss查看 TCP 连接状态。如果测试完毕还看到大量ESTABLISHEDTIME_WAIT,需要检查是否测试结束后没有正确关闭连接。

Windows 下使用:

netstat -ano | findstr "5201"

也可以看到本地端口和远程端口处于什么状态。

10. 常见 TCP/UDP 问题与排查方法

下面是开发与运维中经常遇到的网络问题,按现象、原因、排查步骤和解决方案整理。

问题现象可能原因排查方式解决方案
启动服务时提示bind: only one usage of each socket address端口已经被占用,或者上一个服务进程没有退出执行 `netstat -anofindstr 端口ss -lntp
客户端连接服务端超时,tcp connect timeout服务端未启动、防火墙拦截、IP 不可达、服务端没有监听对应端口先 ping 测试 IP,再用telnet IP 端口nc -vz IP 端口测试连通性启动服务端,确认监听地址不限于 127.0.0.1,检查防火墙规则
curl: (35) tcp connection reset by peer服务端主动重置连接;协议版本不匹配;nginx 后端配置错误抓包看是否有 RST 报文,检查服务端日志调整后端服务配置,检查 SSL 协议版本和 keepalive 设置
服务端出现大量CLOSE_WAIT连接应用未调用 close,连接资源泄漏`ss -tanpgrep CLOSE_WAIT` 查看对应进程
服务端出现大量TIME_WAIT连接短连接频繁建立和关闭检查连接建立频率和客户端行为客户端使用连接池或长连接;必要时调整tcp_tw_reuse,但不要盲目开启
UDP 客户端发送数据没有报错,但接收端收不到UDP 无连接,发送端无法感知接收端是否在监听;报文被防火墙丢弃;端口不匹配在服务端抓包确认报文是否到达,查看防火墙规则确认端口和 IP,检查防火墙对 UDP 端口的放行策略,接收端调用 recvfrom 接收
UDP 报文被分片后丢失应用层发送数据超过路径 MTU,IP 层分片后其中一片丢失用 ping 带-M do -s 1472测试 MTU控制 UDP 报文大小,建议不超过 1200-1400 字节,或使用 UDP-Lite、QUIC 等机制
抓包时设置了 UDP 过滤条件但抓到 ICMP使用的是显示过滤器,网卡捕获层没有过滤使用 capture filter,如udp,条件语法与显示过滤器不同在捕获前设置捕获过滤器,或持续用显示过滤器显示udp并忽略其他包
本机客户端连接本机服务端失败,提示Connection refused服务端未监听,或者监听地址不是客户端访问的地址检查ss -lntp是否监听对应接口修改监听地址为0.0.0.0或正确网卡地址
Docker 容器访问外部报docker: dial tcp: connection refused容器内网络访问宿主机或外部服务失败,服务未运行或防火墙拦截进入容器执行curlpingnc测试确认目标服务监听地址、容器网络模式为 host 或 bridge,放行端口

其中,error: listen tcp 127.0.0.1:11434: bind: only one usage of each socket address这类报错非常典型。它意味着进程要绑定的 127.0.0.1:11434 端口已经被占用。常见原因是本机之前启动过 Ollama 或其他本地服务,进程没有退出,再次启动时内核禁止重复绑定同一个地址。排查时先看 11434 端口被谁占用,再决定杀掉旧进程还是修改监听端口。

Windows 下查看端口占用:

netstat -ano | findstr "11434" tasklist | findstr "PID"

Linux 下查看:

ss -lntp | grep 11434 lsof -i :11434

11. 服务端程序设计选型建议

很多开发者写网络程序时,第一版就默认选择 TCP。大多数情况下没有问题,但如果并发连接数非常大、数据实时性要求高,TCP 的维护成本就会体现出来。建议按以下顺序做选择:

  1. 业务要求不丢包,且数据包不大、频率不高,首选 TCP。
  2. 业务要求高吞吐、低延迟,允许少量丢包或应用层做补偿,选择 UDP。
  3. 需要广播或组播,选择 UDP。
  4. 需要可靠传输但不想应用层造轮子,且网络环境复杂,考虑基于 UDP 的 QUIC 协议。
  5. 既有实时传输需求,又要求可靠传输,可以在 UDP 之上实现自己的确认重传机制,但工程复杂度不要低估。
  6. 嵌入式设备或 PLC 通信,优先考虑协议本身的成熟度。Modbus TCP 是 TCP 承载,Modbus RTU 走串口,两者不要混用。

如果选择 TCP,要特别注意粘包和拆包问题。TCP 是字节流协议,不保留应用层消息边界。例如发送方连续发送helloworld,接收方可能一次读到helloworld,也可能分两次读到helloworld。常见做法是在消息头里加长度字段,或者使用固定分隔符、固定长度消息、Protocol Buffers 等序列化方案。

如果选择 UDP,要设计好以下内容:

  • 报文最大长度,避免 IP 分片。
  • 校验机制,UDP 头部的校验和只能覆盖头部和数据,但应用层最好再加 CRC32 或更强校验,尤其是嵌入式场景。
  • 序列号字段,用于乱序排序和去重。
  • 超时重试,例如请求-响应模型里,客户端发送请求后等待响应,超时则重发。
  • 心跳机制,UDP 没有连接状态,需要通过周期性心跳判断对端是否存活。
  • 对端地址绑定,UDP 服务端可以同时接收来自多个客户端的请求,回包时必须使用sendto带上收到的客户端地址,否则客户端收不到。

从代码实现来看,TCP 和 UDP 的另一个明显区别是接收数据的 API。TCP 使用recv(),接收的是任意字节数;UDP 使用recvfrom(),接收的数据报内容以调用方指定的缓冲区长度为准,缓冲区过小会被截断,过大则会浪费内存。

12. 常见误区与思路整理

关于 TCP 和 UDP,至少要纠正以下几点:

  1. UDP 比 TCP 一定快。不对。在无拥塞的小网络上,两者差异不大;在网络拥塞时,TCP 会主动降低速率,UDP 则会持续发送数据导致更严重的丢包。UDP 的“快”来自缺少连接维护和可靠性机制,但代价是数据不可靠。
  2. TCP 比 UDP 更安全。不对。TCP 同样会被欺骗、劫持、攻击,尤其是无加密的明文 TCP 连接。安全性取决于应用层协议和加密层,跟传输层协议关系不大。
  3. UDP 没有连接,所以服务器不需要维护状态。这也不完全对。应用层如果实现了会话机制,仍然需要维护状态。所谓“无连接”只是传输层没有连接状态机。
  4. TCP 一定适合所有可靠场景。不对。如果网络延迟极高、时延抖动大,TCP 的重传机制可能让整体表现比 UDP 更差。许多实时传输协议反而用 UDP 上承载自定义可靠方案。
  5. TCP 端口和 UDP 端口可以同时占用。对。同一个端口号可以同时被 TCP 和 UDP 的 socket 占用,因为协议不同。例如 DNS 服务器同时监听 TCP 53 和 UDP 53。如果报错bind: only one usage of each socket address,说明可能是同协议端口被占用。

13. 调试建议与工程实践总结

在工程实践中,建议养成以下几个习惯:

  1. 记录连接状态。TCP 服务端要定时输出当前连接数、ESTABLISHED数量、CLOSE_WAIT数量,这些是判断资源泄漏的早期信号。
  2. 统一端口规划。把 TCP 业务端口和 UDP 业务端口分开,避免 80、443、8080 等端口被随意占用,写进配置文件而不是写死在代码里。
  3. 抓包先看本机回环。使用 Wireshark 的 loopback 接口,能快速验证协议行为,不需要真实局域网环境。
  4. 防火墙规则要覆盖 UDP。很多人调试 TCP 服务时记得放行端口,调试 UDP 时却经常忽略防火墙,导致客户端发了数据、服务端没收到。
  5. 打日志要包含源地址和端口。UDP 服务端日志必须记录客户端地址,否则多客户端情况下很难排查是哪个设备发来的包。
  6. 批量任务或大量请求场景,建议使用连接池 + 超时重试。TCP 大量短连接会带来 TIME_WAIT 压力,UDP 大量报文则可能引发丢包风暴,这两种现象都是不同的故障特征。

回到最开始的问题:TCP 和 UDP 有什么区别?最简单的判断标准是,TCP 可以看作“打电话”:先接通,逐句确认,听不清就重说;UDP 可以看作“寄平信”:直接投递到门牌号,不保证对方收到,也不保证顺序。选择哪个协议,本质上是业务要什么样的传输保证。理解了三次握手和数据报边界,再看端口占用、连接重置、抓包过滤这些实际问题,思路就会清晰很多。

如果正在排查本地端口冲突,优先使用ssnetstat定位占用进程;如果遇到连接超时,先确认监听地址和防火墙;如果是 UDP 测试,务必用服务端抓包和丢包统计作为最终依据。这套方法能覆盖绝大多数网络协议开发场景,建议直接收藏备用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 7:28:16

全球水系SHP数据处理指南:线面分离、投影转换与导出实操

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/8 7:27:50

用ESLint理念校验GeoJSON数据:GeoLint实战指南

之前在做地图可视化项目时&#xff0c;数据同学导出一份.geojson文件&#xff0c;前端页面加载后地图上什么都没有&#xff0c;浏览器控制台也没有任何报错。排查到最后发现&#xff0c;coordinates数组里混入了好几个空数组&#xff0c;导致部分要素的几何解析直接失败&#x…

作者头像 李华
网站建设 2026/9/8 7:27:03

FPGA数字钟设计:从时钟域到上板调试的完整实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/8 7:26:11

8FSK扩频系统误码率仿真全解析:从原理到MATLAB实践

最近一个做水下通信课题的师弟跑过来问我&#xff0c;为什么他的8FSK加扩频的MATLAB误码率仿真曲线&#xff0c;跟理论值差了十万八千里。我帮他查了两天代码&#xff0c;发现里面至少有三个典型错误&#xff1a;扩频根本没起到作用、噪声功率算错了、统计的误码数太少导致曲线…

作者头像 李华
网站建设 2026/9/8 7:25:51

纯前端实现Web版文本Diff工具:从零构建行级差异对比页面

简介&#xff1a;一个基于 Web 技术的轻量级 Git diff 可视化工具&#xff0c;面向需要快速查看代码差异的开发者、前端学习者&#xff0c;以及希望摆脱命令行操作的临时用户&#xff0c;无需掌握 Git 命令即可使用。它用浏览器界面还原了 Git 版本控制系统中 diff 的核心功能&…

作者头像 李华
网站建设 2026/9/8 7:25:47

模型生产验收指南:从“命令跑通”到“稳定上线”的鸿沟

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华