在网络密林中传递轻盈信使 —— TouchSocket 的 UdpSession 探秘

前言 --- 一封来自远方的信

小李是一个物联网工程师,他正在构建一个分布式监控系统。系统里有很多传感器节点,它们可能部署在厂房角落、室外机房、甚至是偏远的棚区。主站服务器需要和这些节点 轻量、快速、可靠 地通信。TCP 有连接开销、建立慢;而 UDP 轻便、高效,却对丢包敏感。幸运的是,TouchSocket 提供了 UdpSession 组件,它就像一个灵活的邮差,能在网络密林中穿梭,传递消息。


一、什么是 UdpSession?

UdpSession 是 TouchSocket 提供的一个基础 UDP 通信组件。它属于 TouchSocket.Sockets 命名空间,由 TouchSocket.dll 提供。([TouchSocket][1])

它既可以作为 UDP 服务(Server) ,也可以作为 UDP 客户端(Client)。在许多场景中,它是最轻量、最基础的 UDP 通信构件。([TouchSocket][1])


二、核心特点 --- 为什么选择 UdpSession?

UdpSession 有几个非常吸引人的特性:

  • 简单易用:API 直观,非常适合快速构建 UDP 通信。 ([TouchSocket][1])
  • 多线程重叠 I/O:高并发下依然高效。 ([TouchSocket][1])
  • 内存池支持:减少频繁分配 / 释放内存的开销。 ([TouchSocket][1])
  • 高性能:适合高频消息场景。 ([TouchSocket][1])
  • 支持组播 (Multicast) 和广播 (Broadcast):灵活构建不同 UDP 通信模型。 ([TouchSocket][2])
  • 插件扩展机制:可以在收到数据时插入插件逻辑 (IUdpReceivedPlugin)。 ([TouchSocket][1])
  • 跨平台:适配多种 .NET 平台。 ([TouchSocket][1])

三、典型应用场景

想象以下这些场景:

  1. 物联网设备通信:主站与多个远程节点之间发送心跳、状态或控制命令。
  2. 组播消息:多个客户端加入一个组播组 (Multicast),一起接收组播数据。
  3. 广播场景:广播消息给网络上的所有节点(或某子网),例如发现 / 配置阶段。
  4. 实时监控:对时延敏感,但对部分丢包可容忍的状态更新。

这些场景非常符合 UdpSession 的能力。


四、如何使用 UdpSession ------ 从 "开启邮件站" 到 "发送信件"

下面通过一个故事 + 示例代码说明如何使用 UdpSession

4.1 启动一个 UDP "小站"(Server)

小李决定在服务器端运行一个 UdpSession,接收所有传感器节点发来的状态消息:

csharp 复制代码
var udpService = new UdpSession();

// 收到数据时触发
udpService.Received = (session, e) =>
{
    // e.ByteBlock 是接收到的数据
    string msg = e.ByteBlock.ToString();  
    Console.WriteLine($"收到来自 {e.EndPoint} 的消息:{msg}");
    return EasyTask.CompletedTask;
};

// 配置监听端口 (例如 7789)
udpService.Setup(new TouchSocket.Core.TouchSocketConfig()
    .SetBindIPHost(new TouchSocket.Core.IPHost(7789)));
udpService.Start();

Console.WriteLine("UDP 服务已启动,等待接收消息 ...");

这里:

  • SetBindIPHost 用来指定本地要绑定 (监听) 的端口。([TouchSocket][1])
  • Start() 启动 UDP 会话。([TouchSocket][1])

4.2 作为客户端发送 / 接收 --- 小站之外的小邮差

在某个边缘设备 (或控制端),小李也可以用 UdpSession 作为客户端:

csharp 复制代码
var udpClient = new UdpSession();
udpClient.Setup(new TouchSocket.Core.TouchSocketConfig()
    // 绑定一个本地端口 (可以选 0,让系统分配)  
    .SetBindIPHost(new TouchSocket.Core.IPHost(7788)));

udpClient.Start();

// 假设主站地址是 192.168.1.100:7789
var remoteEP = new System.Net.IPEndPoint(
    System.Net.IPAddress.Parse("192.168.1.100"), 7789);

string text = "SensorStatus: OK";
byte[] data = System.Text.Encoding.UTF8.GetBytes(text);
await udpClient.SendAsync(remoteEP, data, 0, data.Length);

Console.WriteLine("已发送状态到主站");

在客户端模式下,如果不设置 SetBindIPHost,那么这个 UdpSession 可能无法接收数据 。官方文档提醒:如果你不知道该绑定哪个端口,可以绑定到 0 端口 (系统会给一个空闲端口)。([TouchSocket][1])


五、接收数据:委托 vs 插件

UdpSession 提供两种方式接收数据:

5.1 通过 Received 委托

像上面示例那样,直接给 Received 属性赋值一个回调。这是最简单直观的方式。([TouchSocket][1])

5.2 使用 插件 (Plugin)

如果业务比较复杂,或者你想把 "业务处理 / 校验 /日志 /过滤" 和底层接收逻辑分离,可以用插件机制。

例如,定义一个插件类:

csharp 复制代码
public class MyUdpReceivePlugin : PluginBase, TouchSocket.Sockets.IUdpReceivedPlugin
{
    public async Task OnUdpReceived(IUdpSession session, UdpReceivedDataEventArgs e)
    {
        string msg = e.ByteBlock.ToString();
        Console.WriteLine($"[插件] 收到消息:{msg} 来自 {e.EndPoint}");
        // 继续下一个插件 / 默认处理
        await e.InvokeNext();
    }
}

然后在配置中注册这个插件:

csharp 复制代码
var udpService = new UdpSession();
udpService.Setup(new TouchSocket.Core.TouchSocketConfig()
    .SetBindIPHost(new TouchSocket.Core.IPHost(7789))
    .ConfigurePlugins(p => p.Add<MyUdpReceivePlugin>())
);
udpService.Start();

这样,插件可以在接收到数据时插入你的逻辑 (校验 / 日志 /业务),更灵活。([TouchSocket][1])


六、发送数据 --- 灵活策略

UdpSession 支持多种发送方式:

  1. 发送到指定地址

    你可以指定 EndPoint,向任意目标发送:

    csharp 复制代码
    await udpSession.SendAsync(remoteEP, buffer, offset, length);

    ([TouchSocket][1])

  2. 发送到默认地址

    如果你在配置里设置了 RemoteIPHost (远程默认地址),可以用不带 EndPointSendAsync

    csharp 复制代码
    await udpSession.SendAsync(buffer, 0, buffer.Length);

    这种方式在客户端角色时非常有用。([TouchSocket][1])

  3. 响应接收到的数据源

    当你在 Received 回调或插件里处理数据时,可以取到 e.EndPoint (客户端发来的地址),然后回复:

    csharp 复制代码
    await session.SendAsync(e.EndPoint, responseBytes, 0, responseBytes.Length);

    这样可以原路返回给发送方。([TouchSocket][1])


七、进阶玩法 --- 组播与广播 (Multicast / Broadcast)

小李为了让多个节点同时监听某些命令 (例如"全网同步时间" 或 "广播配置命令"),决定使用组播或广播功能:

  • 广播 (Broadcast) :通过设置 UseBroadcast,UdpSession 支持广播。([TouchSocket][2])
  • 组播 (Multicast) :启动后,通过 JoinMulticastGroup(...) 加入一个组播组。这样加入该组的多个 UdpSession 实例都能接收到相同的数据包。([TouchSocket][2])

广播 / 组播非常适合 "一对多" 通信。


八、小李的真实场景:构建健康检查机制

结合他的物联网系统,小李做了这样一个机制:

  1. 所有节点 (UDP 客户端) 向主站周期性发送 "心跳包" (Heartbeat),内容是节点 ID 和状态。
  2. 主站 (UDP 服务) 收到心跳后,用插件记录日志 (比如记录节点最后在线时间)。
  3. 主站 每隔一段时间广播一个 "检查配置版本" 的广播消息 (Broadcast),告诉所有节点检查是否需要下载新配置。
  4. 节点 收到广播后,如果配置版本落后,就向主站发一个 "请求配置" 消息。

借助 UdpSession,小李的机制轻量、高效,而且非常灵活。


九、使用提醒与注意事项

  • 虽然 UDP 轻量,但不可靠:可能丢包、乱序。业务逻辑需要考虑重发、确认机制。
  • 绑定端口:如果你作为客户端通信,并且希望接收数据,一定要绑定合适的本地端口 (或设置为 0 让系统分配)。 ([TouchSocket][1])
  • 插件顺序:使用多个 IUdpReceivedPlugin 时,插件的注册顺序决定调用顺序。
  • 内存池:利用好内存池可以大幅降低 GC 和内存分配压力。
  • 多播、防火墙:如果使用组播 / 广播,要注意网络设备 (路由器、交换机) 是否支持组播 /广播,以及防火墙规则。

十、小结 --- 为什么推荐 UdpSession

  • 轻量、基础:UdpSession 是最基础、最简单的 UDP 会话组件。
  • 高性能 + 低开销:支持内存池、多线程重叠 IO。
  • 灵活通信模型:单播、广播、组播都能覆盖。
  • 插件架构:可以在接收阶段插入业务逻辑 (日志、验证、转发等)。
  • 跨平台:.NET 多平台下可用,非常适合物联网 /分布式系统。

相关推荐
嵌入式-小王1 小时前
每天掌握一个网络协议----ICMP
网络·网络协议·ping
麦麦鸡腿堡1 小时前
Java_网络编程_InetAddress类与Socket类
java·服务器·网络
Awkwardx1 小时前
Linux网络编程—应用层协议HTTP
网络·网络协议·http
4***v2141 小时前
详解 为什么 tcp 会出现 粘包 拆包 问题
网络·tcp/ip·php
老前端的功夫2 小时前
前端浏览器缓存深度解析:从网络请求到极致性能优化
前端·javascript·网络·缓存·性能优化
p66666666684 小时前
vmware虚拟机的三种网络配置详细介绍,包能解决虚拟机网络问题
网络
赖small强5 小时前
【Linux 网络基础】Linux 平台 DHCP 运作原理与握手过程详解
linux·网络·dhcp
Mu.3875 小时前
计算机网络模型
网络·网络协议·计算机网络·安全·http·https
xixixi777777 小时前
解析一下传输安全——“它是什么”,更是关于“它为何存在”、“如何实现”以及“面临何种挑战与未来”
网络·安全·通信