using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace JoyD.Windows.CS.Toprie
{
///
/// UDP通信管理器,负责管理所有UDP通信,实现请求-响应匹配和状态管理
/// 防止异步数据相互影响
///
public class UdpCommunicationManager : IDisposable
{
// 单例实例
private static readonly UdpCommunicationManager _instance = new UdpCommunicationManager();
// 命令队列
private readonly Queue _requestQueue = new Queue();
// 请求映射表,用于匹配请求和响应
private readonly Dictionary _activeRequests = new Dictionary();
// 锁对象,保护共享资源
private readonly object _queueLock = new object();
private readonly object _requestLock = new object();
// UDP客户端实例
private UdpClient _udpClient;
// 工作线程
private Thread _workerThread;
private bool _isRunning;
// 信号量,用于通知工作线程有新请求
private AutoResetEvent _requestAvailable = new AutoResetEvent(false);
// 默认端口
private const int DEFAULT_UDP_PORT = 18890;
// 请求超时时间(毫秒)
private const int DEFAULT_TIMEOUT = 500;
///
/// 获取UdpCommunicationManager的单例实例
///
public static UdpCommunicationManager Instance => _instance;
///
/// 私有构造函数,初始化UDP通信管理器
///
private UdpCommunicationManager()
{
Initialize();
}
///
/// 初始化UDP通信管理器
///
private void Initialize()
{
try
{
// 创建UDP客户端
_udpClient = new UdpClient();
_udpClient.Client.ReceiveTimeout = DEFAULT_TIMEOUT;
// 启动工作线程
_isRunning = true;
_workerThread = new Thread(ProcessRequests) { IsBackground = true };
_workerThread.Start();
Console.WriteLine("UDP通信管理器已初始化");
}
catch (Exception ex)
{
Console.WriteLine($"UDP通信管理器初始化失败: {ex.Message}");
}
}
///
/// 处理请求队列的工作线程函数
///
private void ProcessRequests()
{
while (_isRunning)
{
// 等待请求可用信号
_requestAvailable.WaitOne();
if (!_isRunning) break;
UdpRequest request = null;
// 从队列中获取请求
lock (_queueLock)
{
if (_requestQueue.Count > 0)
{
request = _requestQueue.Dequeue();
}
}
if (request != null)
{
// 处理请求
ProcessRequest(request);
}
}
}
///
/// 处理单个UDP请求
///
/// UDP请求对象
private void ProcessRequest(UdpRequest request)
{
try
{
Console.WriteLine($"处理UDP请求: {request.RequestId}, 目标: {request.TargetIp}:{request.Port}");
// 将请求添加到活动请求列表
lock (_requestLock)
{
_activeRequests[request.RequestId] = request;
}
// 发送UDP数据报
_udpClient.Send(request.Data, request.Data.Length, request.TargetIp, request.Port);
Console.WriteLine($"UDP命令已发送: {Encoding.ASCII.GetString(request.Data)}");
// 启动异步接收响应
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
IAsyncResult ar = _udpClient.BeginReceive(result =>
{
try
{
byte[] responseData = _udpClient.EndReceive(result, ref remoteEndPoint);
HandleResponse(request.RequestId, responseData);
}
catch (Exception ex)
{
Console.WriteLine($"接收UDP响应异常: {ex.Message}");
HandleTimeout(request.RequestId);
}
}, null);
// 设置超时处理(兼容.NET Framework 4.0)
ThreadPool.QueueUserWorkItem(state =>
{
string requestId = (string)state;
Thread.Sleep(request.Timeout);
HandleTimeout(requestId);
}, request.RequestId);
}
catch (Exception ex)
{
Console.WriteLine($"处理UDP请求异常: {ex.Message}");
request.OnResponse?.Invoke(null, true); // 通知请求失败
// 从活动请求列表中移除
lock (_requestLock)
{
_activeRequests.Remove(request.RequestId);
}
}
}
///
/// 处理接收到的UDP响应
///
/// 请求ID
/// 响应数据
private void HandleResponse(string requestId, byte[] responseData)
{
UdpRequest request = null;
// 查找对应的请求
lock (_requestLock)
{
if (_activeRequests.TryGetValue(requestId, out request))
{
_activeRequests.Remove(requestId);
}
}
if (request != null)
{
Console.WriteLine($"收到UDP响应: {requestId}, 长度: {responseData?.Length ?? 0}");
request.OnResponse?.Invoke(responseData, false); // 通知请求成功
}
}
///
/// 处理请求超时
///
/// 请求ID
private void HandleTimeout(string requestId)
{
UdpRequest request = null;
// 查找对应的请求
lock (_requestLock)
{
if (_activeRequests.TryGetValue(requestId, out request))
{
_activeRequests.Remove(requestId);
}
}
if (request != null)
{
Console.WriteLine($"UDP请求超时: {requestId}");
request.OnResponse?.Invoke(null, true); // 通知请求超时
}
}
///
/// 发送UDP请求
///
/// 目标IP地址
/// 要发送的数据
/// 目标端口,默认为18890
/// 超时时间(毫秒),默认为500
/// 包含响应数据的Task
public Task SendRequestAsync(string targetIp, byte[] data, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT)
{
var tcs = new TaskCompletionSource();
string requestId = Guid.NewGuid().ToString();
var request = new UdpRequest
{
RequestId = requestId,
TargetIp = targetIp,
Port = port,
Data = data,
Timeout = timeout,
OnResponse = (response, isTimeout) =>
{
if (isTimeout)
{
tcs.TrySetResult(null);
}
else
{
tcs.TrySetResult(response);
}
}
};
// 将请求添加到队列
lock (_queueLock)
{
_requestQueue.Enqueue(request);
}
// 通知工作线程有新请求
_requestAvailable.Set();
return tcs.Task;
}
///
/// UDP请求结果枚举
///
public enum RequestResult
{
///
/// 请求成功
///
Success,
///
/// 请求超时
///
Timeout,
///
/// 网络错误
///
NetworkError,
///
/// 处理错误
///
ProcessingError,
///
/// 无效响应
///
InvalidResponse
}
///
/// 使用独立UDP客户端发送请求并接收响应(即用即销毁模式)
///
/// 目标IP地址
/// 要发送的数据
/// 目标端口
/// 超时时间(毫秒)
/// 响应数据,如果超时或出错则返回null
private byte[] SendRequestWithDisposableUdp(string targetIp, byte[] data, int port, int timeout)
{
using (UdpClient udpClient = new UdpClient())
{
try
{
// 设置超时时间
udpClient.Client.ReceiveTimeout = timeout;
// 发送数据
IPEndPoint targetEndPoint = new IPEndPoint(IPAddress.Parse(targetIp), port);
udpClient.Send(data, data.Length, targetEndPoint);
// 接收响应
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
byte[] responseData = udpClient.Receive(ref remoteEndPoint);
return responseData;
}
catch (SocketException ex)
{
if (ex.SocketErrorCode == SocketError.TimedOut)
{
Console.WriteLine($"UDP请求执行超时({timeout}ms)");
}
else
{
Console.WriteLine($"UDP通信错误: {ex.Message}");
}
return null;
}
catch (Exception ex)
{
Console.WriteLine($"发送UDP请求时发生错误: {ex.Message}");
return null;
}
}
}
///
/// 同步发送UDP请求
///
/// 目标IP地址
/// 要发送的数据
/// 目标端口,默认为18890
/// 超时时间(毫秒),默认为500
/// 返回的响应数据
/// 请求结果
public RequestResult SendRequest(string targetIp, byte[] data, out byte[] response, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT)
{
response = null;
try
{
// 使用新的即用即销毁UDP方法
response = SendRequestWithDisposableUdp(targetIp, data, port, timeout);
if (response != null)
{
return RequestResult.Success;
}
// 如果响应为null,可能是超时或网络错误
// 在SendRequestWithDisposableUdp方法中已经记录了具体错误
return RequestResult.NetworkError;
}
catch (Exception ex)
{
Console.WriteLine($"处理UDP请求结果时发生错误: {ex.Message}");
return RequestResult.ProcessingError;
}
}
///
/// 同步发送UDP请求(兼容旧版本)
///
/// 目标IP地址
/// 要发送的数据
/// 目标端口,默认为18890
/// 超时时间(毫秒),默认为500
/// 响应数据,如果超时则返回null
public byte[] SendRequest(string targetIp, byte[] data, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT)
{
SendRequest(targetIp, data, out byte[] response, port, timeout);
return response;
}
///
/// 异步发送字符串命令的UDP请求
///
/// 目标IP地址
/// 要发送的命令字符串
/// 目标端口,默认为18890
/// 超时时间(毫秒),默认为500
/// 包含响应字符串的Task
public Task SendRequestAsync(string targetIp, string command, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT)
{
byte[] data = Encoding.ASCII.GetBytes(command);
Task dataTask = SendRequestAsync(targetIp, data, port, timeout);
// 创建一个新的Task用于返回字符串结果
TaskCompletionSource tcs = new TaskCompletionSource();
dataTask.ContinueWith(task => {
if (task.IsFaulted)
{
tcs.SetException(task.Exception);
}
else if (task.IsCanceled)
{
tcs.SetCanceled();
}
else
{
byte[] result = task.Result;
string stringResult = result != null ? Encoding.ASCII.GetString(result) : null;
tcs.SetResult(stringResult);
}
});
return tcs.Task;
}
///
/// 同步发送字符串命令的UDP请求
///
/// 目标IP地址
/// 要发送的命令
/// 超时时间(毫秒)
/// 返回的响应内容
/// 请求结果
public RequestResult SendRequest(string targetIp, string command, int timeoutMs, out string response)
{
response = null;
try
{
var task = SendRequestAsync(targetIp, command, DEFAULT_UDP_PORT, timeoutMs);
bool completed = task.Wait(timeoutMs + 50); // 额外添加50ms作为缓冲
if (completed)
{
response = task.Result;
if (response != null)
{
// 验证响应格式是否符合预期
if (response.Length > 0 && (response.StartsWith("+RET:") || response.Contains(":")))
{
return RequestResult.Success;
}
Console.WriteLine($"命令 '{command}' 收到无效响应: '{response}'");
return RequestResult.InvalidResponse;
}
return RequestResult.NetworkError;
}
Console.WriteLine($"命令 '{command}' 执行超时({timeoutMs}ms)");
return RequestResult.Timeout;
}
catch (TimeoutException)
{
Console.WriteLine($"命令 '{command}' 执行超时异常");
return RequestResult.Timeout;
}
catch (Exception ex)
{
Console.WriteLine($"发送命令 '{command}' 时发生错误: {ex.Message}");
return RequestResult.ProcessingError;
}
}
///
/// 清理资源
///
public void Dispose()
{
_isRunning = false;
_requestAvailable.Set(); // 唤醒工作线程以便它可以退出
if (_workerThread != null && _workerThread.IsAlive)
{
_workerThread.Join(1000); // 等待工作线程退出
}
if (_udpClient != null)
{
_udpClient.Close();
_udpClient = null;
}
if (_requestAvailable != null)
{
_requestAvailable.Dispose();
_requestAvailable = null;
}
// 清空请求队列和活动请求
lock (_queueLock)
{
_requestQueue.Clear();
}
lock (_requestLock)
{
_activeRequests.Clear();
}
Console.WriteLine("UDP通信管理器已释放");
}
///
/// UDP请求类,封装单个UDP请求的信息
///
private class UdpRequest
{
public string RequestId { get; set; }
public string TargetIp { get; set; }
public int Port { get; set; }
public byte[] Data { get; set; }
public int Timeout { get; set; }
public Action OnResponse { get; set; }
}
}
}