C# UDP通信方法 C#如何实现UDP Socket编程

来源:这里教程网 时间:2026-02-21 17:40:35 作者:

UDP通信用
UdpClient
还是
Socket

日常开发中优先用

UdpClient
,它封装了底层
Socket
的细节,写法简洁、不易出错;只有需要精细控制(如设置
IP_PKTINFO
、绑定到任意接口、复用端口等)时才直接操作
Socket

注意:

UdpClient
默认不支持异步接收多个包的并发处理(单次
Receive
阻塞),若需高吞吐或长连接模型,得配合线程/任务或改用
Socket.ReceiveFromAsync

UdpClient
构造后自动创建并绑定
Socket
,调用
Close()
Dispose()
才释放资源
直接用
Socket
时,必须显式调用
Bind()
,且协议类型要设为
SocketType.Dgram
+
ProtocolType.Udp
UdpClient
Client
属性可拿到底层
Socket
实例,用于做高级配置(如
SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true)

发送 UDP 包:
UdpClient.Send
的关键参数

发送前不用手动指定目标 IP 端口——

UdpClient
支持两种模式:一种是构造时绑定本地端口(用于接收),发送时用
Send(byte[], int, IPEndPoint)
显式传目标地址;另一种是用
Connect(IPEndPoint)
后直接调用
Send(byte[], int)
,此时目标地址被“固定”,后续所有
Send
都发往该地址。

容易踩的坑:

Connect()
后不能再接收其他地址的数据(底层
Socket
被限制为“已连接”状态),且
Receive()
会抛
SocketException
(错误码 10057)。

目标
IPEndPoint
必须含有效 IPv4/IPv6 地址和非零端口,
IPAddress.Any
IPAddress.IPv6Any
是非法目标地址
发送缓冲区大小受系统 UDP 缓冲区限制(通常 64KB 左右),超长数据会被静默截断,不报错也不抛异常 无连接特性意味着发送成功 ≠ 对方收到,也无重传、确认机制

接收 UDP 包:如何避免
Receive
阻塞主线程?

UdpClient.Receive
是同步阻塞调用,直接放在 UI 线程或主循环里会导致卡死。正确做法是用单独线程、
Task.Run
或基于
SocketAsyncEventArgs
的异步模型。

最简可行方案是启动一个后台任务持续接收:

var client = new UdpClient(8080);
_ = Task.Run(async () =>
{
    while (!cancellationToken.IsCancellationRequested)
    {
        try
        {
            var result = await client.ReceiveAsync();
            Console.WriteLine($"Received {result.Buffer.Length} bytes from {result.RemoteEndPoint}");
        }
        catch (ObjectDisposedException) { break; }
        catch (SocketException ex) when (ex.SocketErrorCode == SocketError.Interrupted) { break; }
    }
});

注意:

UdpClient
不提供原生
ReceiveAsync
(.NET 6+ 才有),旧版本必须用
BeginReceive
/
EndReceive
或转到底层
Socket
调用
ReceiveFromAsync

防火墙与端口绑定常见失败原因

运行时提示“通常每个套接字地址(协议/网络地址/端口)只允许使用一次”(错误码 10048),大概率是端口被占用或未设

ReuseAddress
;提示“由于目标计算机积极拒绝,无法连接”(10061),通常是目标机器没开监听,或 Windows 防火墙拦截了入站 UDP 流量。

绑定
0.0.0.0:8080
表示监听本机所有 IPv4 接口,但 Windows 默认阻止外部访问,需在防火墙中放行该端口(入站规则)
IPAddress.Loopback
(即
127.0.0.1
)只能收本机发的包,跨机器通信必须用实际网卡 IP 或
IPAddress.Any
多个进程不能同时
Bind
到同一端口,除非都设置了
SocketOptionName.ReuseAddress
且至少一个启用了
SO_EXCLUSIVEADDRUSE
(Windows)或
SO_REUSEPORT
(Linux/macOS)

UDP 没有连接状态,所以抓包看到 SYN/RST 等 TCP 标志位一定不是 UDP 流量;调试时优先用

netstat -uanp
(Linux)或
Get-NetUDPEndpoint
(PowerShell)确认端口是否真在监听。

相关推荐

热文推荐