客户端和服务器建立UDP连接,并不是像TCP那样三次握手,而是双方约定IP和端口后,通过socket绑定、发送数据报,必要时调用connect()让内核记录对端四元组,再用应用层心跳和超时重传维持会话。 你可以把UDP想成寄明信片:地址写对就能投递,但丢不丢件、顺序乱不乱,得自己兜底。
客户端和服务器怎么建立UDP连接:先搞清“连接”到底连了什么
UDP协议本身没有连接状态,据IETF RFC 768定义,UDP头部固定8字节,只包含源端口、目的端口、长度和校验和,它不握手、不确认、不重传,所谓“建立UDP连接”,通常有三层含义:
- 应用层会话:双方约定好格式、序列号、心跳和超时。
- 内核层
connect():本地socket绑定远端地址,形成四元组映射。 - NAT层打洞:通过公网服务器交换地址端口,让两边NAT放行。
真正写代码时,服务器端一般bind()固定端口,客户端用sendto()或connect()加send()发第一个包,服务器收到包后,从recvfrom()拿到客户端地址,后续就能按这个地址回包。
UDP没有三次握手,为什么还能调用connect?
connect()在UDP里不发送任何握手包,它做的是:
- 检查路由是否可达。
- 给本地socket绑定一个本地IP和端口。
- 记录远端IP和端口,后续可用
send()和recv()。 - 让内核在收到ICMP端口不可达时,把错误返回给应用层。
connect()只是让内核知道“默认对端是谁”,不是真正建立连接,你依然可能丢包、收不到回应。
UDP连接和TCP连接有什么区别?对比之后再看代码
| 维度 | TCP | UDP |
|---|---|---|
| 连接方式 | 三次握手 | 无握手,应用层约定 |
| 头部开销 | 至少20字节 | 固定8字节 |
| 可靠性 | 确认、重传、按序 | 不保证到达和顺序 |
| 适用场景 | 网页、文件、数据库 | 音视频、游戏、DNS、QUIC |
connect()作用 |
建立连接 | 设置默认对端,绑定四元组 |
业内专家指出,UDP头部只有8字节,比TCP至少20字节更轻量,行业共识认为,UDP适合实时音视频、游戏同步、DNS查询等容忍少量丢包但追求低延迟的场景。
局域网内UDP客户端与服务器通信怎么配置?实操步骤
局域网里没有NAT干扰,UDP通信最容易跑通,你可以在同一网段找两台机器,或者本机开两个终端。
服务器端:绑定端口并等待数据报
用Python写一个最小服务器:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('0.0.0.0', 9999))
print('UDP server listening on 9999')
data, addr = s.recvfrom(1024)
print('from', addr, 'data', data)
s.sendto(b'hello udp client', addr)
这段代码做了三件事:创建UDP socket、绑定0.0.0:9999、收到包后回复。
客户端:发送第一个数据报
客户端可以这样写:
import socket
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.connect(('192.168.1.10', 9999))
c.send(b'ping')
print(c.recv(1024))
这里的connect()没有握手,只是把168.1.10:9999设为默认对端,如果服务器在远端,把IP换成公网IP。
验证:ss、tcpdump、nc
排查时别只盯代码,系统工具更快:
ss -lunp | grep 9999:看服务器是否监听UDP 9999。tcpdump -i any udp port 9999:抓包看请求有没有到。nc -u -l 9999:Linux下快速起一个UDP监听。nc -u 192.168.1.10 9999:快速发UDP包。- Windows可用
Test-NetConnection配合端口工具,或直接用Wireshark看UDP流。
如果服务器没收到,先看tcpdump有没有包,有包没回,查应用;没包,查网络和防火墙。
公网服务器UDP端口不通怎么排查?场景化检查清单
公网环境比局域网复杂,据统计,公网UDP不通的案例里,较大比例与安全组、防火墙或NAT映射有关,按下面顺序查,基本能定位。
云安全组与主机防火墙
云服务器通常有两层防火墙:
- 云平台安全组:入方向放行UDP 9999。
- 主机防火墙:
firewall-cmd --add-port=9999/udp --permanent,然后firewall-cmd --reload。 - iptables:
iptables -A INPUT -p udp --dport 9999 -j ACCEPT。 - Windows防火墙:新建入站规则,协议选UDP,端口填9999。
只开TCP不开UDP,是常见错误。
NAT与端口映射
如果服务器在路由器后面,需要做端口映射:
- 路由器后台找到“虚拟服务器”或“端口转发”。
- 外部端口9999,内部IP填服务器局域网IP。
- 协议选UDP,或TCP/UDP都选。
- 保存后从公网发UDP包测试。
没有公网IP时,NAT映射也做不了,这时要么用云服务器中转,要么走UDP打洞。
抓包定位丢包方向
在服务器和客户端同时抓包:
- 客户端
tcpdump -i any udp port 9999。 - 服务器
tcpdump -i any udp port 9999。 - 客户端有包、服务器没有,查中间网络。
- 服务器有包、客户端没收到,查回包路由和安全组。
- 两边都有包但应用没处理,查
bind()地址和端口。
UDP没有重传,丢一个包就是丢了,抓包是最高效的证据。
跨地域UDP连接不稳定怎么办?长连接保活与打洞思路
跨地域走公网,延迟和丢包都会上升,UDP没有内置保活,应用层要自己维护会话。
应用层心跳与超时重传
- 客户端每3到5秒发一次心跳包。
- 服务器超过10到15秒没收到,标记离线。
- 关键指令带序列号,收方去重和排序。
- 重要数据加确认和重传,普通状态包可以丢。
心跳不是TCP的专利,UDP会话靠心跳续命,也靠心跳发现断线。
UDP打洞:通过公网服务器交换地址
两台设备都在NAT后,不能直接互发,流程是:
- 双方先连公网服务器,服务器记录各自的公网IP和端口。
- 服务器把对方的地址端口告诉两边。
- 两边同时向对方公网地址发UDP包。
- NAT设备看到出站包,建立映射,后续回包就能进来。
这就是UDP打洞,STUN用于获取公网映射,TURN用于打洞失败时中转,WebRTC、部分游戏联机都用这套。
云服务器UDP带宽价格怎么选?先看流量模型
价格敏感的项目,先算流量模型:
- 小包高频:看PPS和带宽峰值,别只看流量。
- 大包低频:按流量计费更划算。
- 实时音视频:选按带宽计费,避免突发流量超限。
- 跨地域传输:加钱买优质线路,能降丢包和抖动。
云厂商的UDP带宽价格差异大,按量付费适合测试,包年包月适合稳定业务,别为用不到的峰值买单,也别让带宽成为瓶颈。
收束:UDP“连接”靠约定,不靠握手
UDP没有真正的连接,客户端和服务器建立的是应用层会话和内核四元组映射,把绑定、发包、心跳、超时和NAT处理做扎实,UDP通信就能稳定跑起来,UDP不保证送达,但你可以用设计保证业务可靠。
客户端和服务器怎么建立UDP连接:常见问题解答
UDP connect之后真的建立连接了吗?
没有。connect()只是设置默认对端,绑定本地地址,并让内核记录远端信息,它不发送握手包,也不保证对方在线。
UDP服务器需要监听吗?
需要,服务器端必须调用bind()绑定IP和端口,然后通过recvfrom()接收数据报,不绑定端口,内核不知道把UDP包交给哪个进程。
为什么UDP端口通了但收不到数据?
可能原因包括:安全组只开了TCP、主机防火墙拦了UDP、NAT映射没做、客户端发到了错误IP、服务器bind()在错误网卡、或者回包被中间网络丢弃,先用tcpdump确认包到了哪一端,再看应用层是否处理。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/755637.html





