//using System.Text; //using MessagePack; //using Microsoft.Extensions.Hosting; //using NetMQ; //using NetMQ.Monitoring; // ★ 1. 必须引用 Monitoring 命名空间 //using NetMQ.Sockets; //using SHH.CameraSdk; //using SHH.Contracts; //namespace SHH.CameraService; //public class CommandClientWorker : BackgroundService //{ // private readonly ServiceConfig _config; // private readonly CommandDispatcher _dispatcher; // private readonly InterceptorPipeline _pipeline; // // 管理多个 Socket // private readonly List _sockets = new(); // // ★ 2. 新增:保存 Monitor 列表,防止被 GC 回收 // private readonly List _monitors = new(); // private NetMQPoller? _poller; // public CommandClientWorker( // ServiceConfig config, // CommandDispatcher dispatcher, // InterceptorPipeline pipeline) // { // _config = config; // _dispatcher = dispatcher; // _pipeline = pipeline; // } // protected override async Task ExecuteAsync(CancellationToken stoppingToken) // { // await Task.Yield(); // if (!_config.ShouldConnect || _config.CommandEndpoints.Count == 0) return; // _poller = new NetMQPoller(); // // ------------------------------------------------------------- // // 核心修改区:建立连接并挂载监控器 // // ------------------------------------------------------------- // foreach (var ep in _config.CommandEndpoints) // { // try // { // var socket = new DealerSocket(); // socket.Options.Identity = Encoding.UTF8.GetBytes(_config.AppId); // var monitorUrl = $"inproc://monitor_{Guid.NewGuid():N}"; // var monitor = new NetMQMonitor(socket, monitorUrl, SocketEvents.Connected); // monitor.Connected += async (s, args) => // { // Console.WriteLine($"[指令] 网络连接建立: {ep.Uri} -> 正在补发注册包..."); // await SendRegisterAsync(socket); // }; // // ★★★ 修正点:使用 AttachToPoller 代替 Add ★★★ // // 错误写法: _poller.Add(monitor); // monitor.AttachToPoller(_poller); // // 依然需要保存引用,防止被 GC 回收 // _monitors.Add(monitor); // socket.Connect(ep.Uri); // socket.ReceiveReady += OnSocketReceiveReady; // _sockets.Add(socket); // _poller.Add(socket); // Console.WriteLine($"[指令] 通道初始化完成: {ep.Uri} (带自动重连监控)"); // } // catch (Exception ex) // { // Console.WriteLine($"[指令] 连接初始化异常: {ex.Message}"); // } // } // if (_sockets.Count == 0) return; // // ================================================================= // // 6. 绑定 ACK 逻辑 (保持不变) // // ================================================================= // _dispatcher.OnResponseReady += async (result) => // { // try // { // byte[] resultBytes = MessagePackSerializer.Serialize(result); // var ctx = await _pipeline.ExecuteSendAsync(ProtocolHeaders.CommandResult, resultBytes); // if (ctx != null) // { // foreach (var socket in _sockets) // { // socket.SendMoreFrame(ctx.Protocol).SendFrame(ctx.Data); // } // Console.WriteLine($"[指令] ACK 已广播 (ID: {result.RequestId})"); // } // } // catch (Exception ex) // { // Console.WriteLine($"[ACK] 发送失败: {ex.Message}"); // } // }; // // ================================================================= // // 7. 启动 Poller // // ================================================================= // // 注意:我们不需要手动发第一次注册包了, // // 因为 Poller 启动后,底层 TCP 会建立连接,从而触发 monitor.Connected 事件, // // 事件里会自动发送注册包。这就是“自动档”的好处。 // _poller.RunAsync(); // // 阻塞直到取消 // while (!stoppingToken.IsCancellationRequested) // { // await Task.Delay(1000, stoppingToken); // } // // 清理 // _poller.Stop(); // _poller.Dispose(); // foreach (var m in _monitors) m.Dispose(); // 释放监控器 // foreach (var s in _sockets) s.Dispose(); // } // // ================================================================= // // ★ 8. 抽离出的注册包发送逻辑 (供 Monitor 调用) // // ================================================================= // private async Task SendRegisterAsync(DealerSocket targetSocket) // { // try // { // var registerPayload = new RegisterPayload // { // Protocol = ProtocolHeaders.ServerRegister, // InstanceId = _config.AppId, // ProcessId = Environment.ProcessId, // Version = "1.0.0", // ServerIp = "127.0.0.1", // 建议优化:获取本机真实IP // WebApiPort = _config.BasePort, // StartTime = DateTime.Now // }; // byte[] regData = MessagePackSerializer.Serialize(registerPayload); // // 执行拦截器 // var ctx = await _pipeline.ExecuteSendAsync(ProtocolHeaders.ServerRegister, regData); // if (ctx != null) // { // // 直接向触发事件的那个 Socket 发送 // // DealerSocket 允许在连接未完全就绪时 Send,它会缓存直到网络通畅 // targetSocket.SendMoreFrame(ctx.Protocol).SendFrame(ctx.Data); // // Console.WriteLine($"[指令] 身份注册包已推入队列: {targetSocket.Options.Identity}"); // } // } // catch (Exception ex) // { // Console.WriteLine($"[指令] 注册包发送失败: {ex.Message}"); // } // } // private async void OnSocketReceiveReady(object? sender, NetMQSocketEventArgs e) // { // NetMQMessage incomingMsg = new NetMQMessage(); // if (e.Socket.TryReceiveMultipartMessage(ref incomingMsg)) // { // if (incomingMsg.FrameCount >= 2) // { // try // { // string rawProtocol = incomingMsg[0].ConvertToString(); // byte[] rawData = incomingMsg[1].ToByteArray(); // var ctx = await _pipeline.ExecuteReceiveAsync(rawProtocol, rawData); // if (ctx != null) // { // await _dispatcher.DispatchAsync(ctx.Protocol, ctx.Data); // } // } // catch (Exception ex) // { // Console.WriteLine($"[指令] 处理异常: {ex.Message}"); // } // } // } // } //}