You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
4.8 KiB
143 lines
4.8 KiB
using CoreAgent.Domain.Interfaces.CustomWSClient;
|
|
using Microsoft.Extensions.Logging;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.WebSockets;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using WebSocket4Net;
|
|
using WebSocket = WebSocket4Net.WebSocket;
|
|
using WebSocketState = WebSocket4Net.WebSocketState;
|
|
|
|
namespace CoreAgent.Infrastructure.Services.CustomWSClient
|
|
{
|
|
public class ObserverCustomWebSocketClient : IObserverCustomWebSocketClient, IDisposable
|
|
{
|
|
private readonly WebSocket _client;
|
|
private readonly ILogger _logger;
|
|
private readonly BlockingCollection<string> _sendQueue;
|
|
private readonly CancellationTokenSource _cancellationTokenSource;
|
|
private readonly Task _sendTask;
|
|
private bool _disposed;
|
|
private const int SEND_INTERVAL_MS = 100; // 发送间隔,可以根据需要调整
|
|
|
|
public ObserverCustomWebSocketClient(WebSocket client, ILogger logger)
|
|
{
|
|
_client = client ?? throw new ArgumentNullException(nameof(client));
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
|
|
_sendQueue = new BlockingCollection<string>();
|
|
_cancellationTokenSource = new CancellationTokenSource();
|
|
_sendTask = Task.Run(ProcessSendQueue);
|
|
|
|
_logger.LogInformation("WebSocket消息发送队列已启动");
|
|
}
|
|
|
|
public void SendMessage(string message)
|
|
{
|
|
if (string.IsNullOrEmpty(message))
|
|
{
|
|
_logger.LogWarning("尝试发送空消息");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
_logger.LogDebug("将消息加入发送队列: {Message}", message);
|
|
_sendQueue.Add(message);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "将消息加入发送队列时发生错误: {Message}", message);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private async Task ProcessSendQueue()
|
|
{
|
|
try
|
|
{
|
|
_logger.LogInformation("开始处理WebSocket消息发送队列");
|
|
foreach (var message in _sendQueue.GetConsumingEnumerable(_cancellationTokenSource.Token))
|
|
{
|
|
try
|
|
{
|
|
await SendMessageInternalAsync(message);
|
|
await Task.Delay(SEND_INTERVAL_MS); // 添加发送间隔
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "发送WebSocket消息时发生错误: {Message}", message);
|
|
}
|
|
}
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
_logger.LogInformation("WebSocket消息发送队列处理已取消");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "WebSocket消息发送队列处理过程中发生错误");
|
|
}
|
|
}
|
|
|
|
private async Task SendMessageInternalAsync(string message)
|
|
{
|
|
if (_client.State != WebSocketState.Open)
|
|
{
|
|
_logger.LogWarning("WebSocket未处于打开状态,无法发送消息。当前状态: {State}, 消息内容: {Message}",
|
|
_client.State, message);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
_logger.LogDebug("正在发送WebSocket消息: {Message}", message);
|
|
await Task.Run(() => _client.Send(message));
|
|
_logger.LogDebug("WebSocket消息发送成功");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "发送WebSocket消息时发生错误: {Message}", message);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!_disposed)
|
|
{
|
|
if (disposing)
|
|
{
|
|
_cancellationTokenSource.Cancel();
|
|
_sendQueue.CompleteAdding();
|
|
try
|
|
{
|
|
_sendTask.Wait(TimeSpan.FromSeconds(5));
|
|
}
|
|
catch (AggregateException ex)
|
|
{
|
|
_logger.LogError(ex, "等待消息发送队列处理完成时发生错误");
|
|
}
|
|
_sendQueue.Dispose();
|
|
_cancellationTokenSource.Dispose();
|
|
}
|
|
_disposed = true;
|
|
}
|
|
}
|
|
|
|
~ObserverCustomWebSocketClient()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
}
|
|
}
|
|
|