NetMQ 协议,支持摄像头增、删、改
This commit is contained in:
@@ -19,43 +19,65 @@ public class NetMqSenderWorker : BackgroundService
|
||||
}
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
Console.WriteLine($"[NetMqSender] 正在连接至服务端: {_target.Config.Endpoint} ...");
|
||||
|
||||
// ★★★ 修正点:必须使用 PublisherSocket 来配合接收端的 SubscriberSocket ★★★
|
||||
// 虽然是 Connect 模式,Publisher 依然可以 Connect
|
||||
using var clientSocket = new PublisherSocket();
|
||||
|
||||
// 设置高水位 (HWM)
|
||||
// 对于 Publisher,如果队列满了,默认行为就是丢弃旧数据,这非常符合视频流需求
|
||||
clientSocket.Options.SendHighWatermark = 1000;
|
||||
|
||||
// 主动连接
|
||||
clientSocket.Connect(_target.Config.Endpoint);
|
||||
|
||||
Console.WriteLine("[NetMqSender] 连接成功,开始从通道搬运数据...");
|
||||
|
||||
await foreach (var payload in _target.Channel.Reader.ReadAllAsync(stoppingToken))
|
||||
// 增加重启保护
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var msg = payload.ToNetMqMessage();
|
||||
Console.WriteLine($"[NetMqSender] 连接至: {_target.Config.Endpoint}");
|
||||
|
||||
// 发送消息
|
||||
// PublisherSocket 的 TrySend 如果没人订阅或者队列满了,通常不会阻塞,而是直接丢弃或返回
|
||||
// 注意:PUB 模式下,第一帧 ("SHH_V1") 会被当作订阅的主题 (Topic)。
|
||||
// 你的接收端订阅了 "" (空字符串),所以能收到以任何字符串开头的数据。
|
||||
bool sent = clientSocket.TrySendMultipartMessage(msg);
|
||||
using var clientSocket = new PublisherSocket();
|
||||
clientSocket.Options.SendHighWatermark = 1000;
|
||||
// 关键:增加 TCP 保活,防止防火墙静默断开长连接
|
||||
clientSocket.Options.TcpKeepalive = true;
|
||||
clientSocket.Options.TcpKeepaliveIdle = TimeSpan.FromSeconds(5);
|
||||
|
||||
if (!sent)
|
||||
clientSocket.Connect(_target.Config.Endpoint);
|
||||
|
||||
int frameCount = 0;
|
||||
|
||||
// 使用更稳健的读取方式
|
||||
await foreach (var payload in _target.Channel.Reader.ReadAllAsync(stoppingToken))
|
||||
{
|
||||
// 这种情况通常意味着网络断了且 HWM 队列也满了
|
||||
Console.WriteLine($"[NetMqSender] 警告: 发送队列已满,正在丢帧...");
|
||||
msg.Clear(); // 手动清理(可选)
|
||||
try
|
||||
{
|
||||
// 1. 构造消息 (内部执行了 MessagePack 序列化)
|
||||
var msg = payload.ToNetMqMessage();
|
||||
|
||||
// 2. 发送
|
||||
bool sent = clientSocket.TrySendMultipartMessage(msg);
|
||||
|
||||
if (!sent)
|
||||
{
|
||||
Console.WriteLine($"[NetMqSender] 发送缓冲区满,丢弃帧: {payload.CameraId}");
|
||||
// ★ 如果没有发送成功,建议显式清理消息帧,防止内存滞留
|
||||
msg.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
frameCount++;
|
||||
if (frameCount % 100 == 0)
|
||||
Console.WriteLine($"[NetMqSender] 已搬运 100 帧至缓冲区.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[NetMqSender] 内部循环异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { break; }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[NetMqSender] 异常: {ex.Message}");
|
||||
// ★★★ 核心改进:捕获异常并等待重试 ★★★
|
||||
// 防止因为一次内存溢出或网络波动导致整个 BackgroundService 永久停止
|
||||
Console.WriteLine($"[NetMqSender] 发生致命异常,5秒后尝试重建连接: {ex.Message}");
|
||||
await Task.Delay(5000, stoppingToken);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 确保每次循环退出(无论是异常还是正常)都清理环境
|
||||
NetMQConfig.Cleanup(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user