using System; using NetMQ; using NetMQ.Sockets; using SHH.Contracts; namespace SHH.NetMQ { /// /// 视频分发服务端 (Publisher) /// 特性:非阻塞、防内存溢出 /// public class DistributorServer : IDisposable { private PublisherSocket _pubSocket; private readonly object _lock = new object(); // 配置:高水位限制 (HWM) // 假设 25fps,设置 50 意味着内存只缓存 2 秒的视频。 // 如果断网超过 2 秒,新来的视频帧直接丢弃,优先保证恢复后的实时性。 private const int HWM_LIMIT = 50; public DistributorServer(string connectionString) { _pubSocket = new PublisherSocket(); // 1. 设置发送缓冲区大小 (防爆内存关键) _pubSocket.Options.SendHighWatermark = HWM_LIMIT; // 2. 绑定地址 (如 tcp://*:5555) _pubSocket.Bind(connectionString); } public void Broadcast(VideoPayload payload) { if (payload == null) return; // 补充发送时间 payload.DispatchTimestamp = DateTime.Now.Ticks; // 准备数据帧 string jsonMeta = payload.GetMetadataJson(); byte[] rawBytes = payload.OriginalImageBytes ?? new byte[0]; byte[] targetBytes = payload.TargetImageBytes ?? new byte[0]; // 使用 NetMQMessage 封装多帧消息 // 这样比手动调三次 Send 更容易管理原子性 var msg = new NetMQMessage(); msg.Append(jsonMeta); // 第1帧 msg.Append(rawBytes); // 第2帧 msg.Append(targetBytes); // 第3帧 lock (_lock) { // 3. 非阻塞发送 (核心防卡死代码) // TimeSpan.Zero 表示:如果缓冲区满了或者发不出去,立即放弃,不等待,返回 false // 这样你的主线程(海康SDK回调)永远不会被卡住 bool sent = _pubSocket.TrySendMultipartMessage(TimeSpan.Zero, msg); if (!sent) { // 这里可以打个日志:Console.WriteLine("警告:网络拥堵,丢帧中..."); } } } public void Dispose() { _pubSocket?.Dispose(); } } }