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; } } } }