using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace LB_VisionProcesses.Communicators.TCom { public class TCPServer : BaseCommunicator { private TcpListener _tcpListener; private Task _tcpListenerTask; CancellationTokenSource ctsListener = new CancellationTokenSource(); private List _clients = new List(); // 用于存储所有连接的客户端 /// /// 是否多播模式(多播模式会将收到的客户端消息转发给其他客户端) /// bool isMultiBroadcast = true; public TCPServer(string name = "TCP服务器") { CommunicatorConnections.Add("地址", "127.0.0.1"); CommunicatorConnections.Add("端口", "1111"); CommunicatorBrand = CommunicatorBrand.TCPServer; CommunicatorName = name; } public override bool Connect() { try { // 创建一个TCP监听器 if (bConnected) Disconnect(); int PORT = 0; if (!int.TryParse(this.CommunicatorConnections["端口"].ToString(), out PORT)) { Msg = string.Format("端口未设置"); return false; } if (!CommunicatorConnections.Contains("地址")) { Msg = string.Format("地址未设置"); return false; } string IP = CommunicatorConnections["地址"].ToString(); _tcpListener = new TcpListener(IPAddress.Parse(IP), PORT); _tcpListener.Start(); bConnected = true; //// 启动心跳线程(服务器不需要心跳线程) //heartbeatThread = new Thread(SendHeartbeat); //heartbeatThread.IsBackground = true; //heartbeatThread.Start(); // 启动监听线程 ctsListener = new CancellationTokenSource(); _tcpListenerTask = ListenForClientsAsync(ctsListener.Token); return true; } catch (Exception ex) { Msg = $"失败,服务器已经启动: {ex.Message}"; return false; } } public override bool Disconnect() { try { bConnected = false; if (_tcpListenerTask != null) ctsListener.Cancel(); if (_tcpListener != null) { _tcpListener.Stop(); _tcpListener = null; } return true; } catch { bConnected = false; Msg = "失败,服务器已经停止"; return true; } } private async Task ListenForClientsAsync(CancellationToken cancellationToken) { while (bConnected && !cancellationToken.IsCancellationRequested) { try { //// 阻塞等待客户端连接 //var tcpClient = _tcpListener.AcceptTcpClient(); //// 将客户端添加到客户端列表中 //lock (_clients) //{ // _clients.Add(tcpClient); //} //// 启动一个线程来处理客户端消息 //var clientThread = new Thread(HandleClientComm); //clientThread.Start(tcpClient); // 异步等待客户端连接(可取消) var tcpClient = await _tcpListener.AcceptTcpClientAsync(cancellationToken); lock (_clients) { _clients.Add(tcpClient); } // 使用 Task.Run 代替 Thread _ = Task.Run(() => HandleClientComm(tcpClient), cancellationToken); } catch { } } } private void HandleClientComm(object obj) { if (obj == null || !(obj is TcpClient)) return; try { var tcpClient = (TcpClient)obj; NetworkStream stream = tcpClient.GetStream(); while (bConnected) { byte[] buffer = new byte[1024]; int bytesRead = stream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; strReceiveMsg = Encoding.UTF8.GetString(buffer, 0, bytesRead); List listRemoveTcpClients = new List(); foreach (var client in _clients) { if (isMultiBroadcast && client != tcpClient) // 如果是多播模式且不是发送者 { try { SendMessageToClient(client, strReceiveMsg); } catch (Exception ex) { Debug.WriteLine($"发送消息到 {client.ToString()} 客户端时发生错误: {ex.Message}"); listRemoveTcpClients.Add(client); } } } foreach (var offlineTcpClient in listRemoveTcpClients) { lock (_clients) { _clients.Remove(offlineTcpClient); } } try { TriggerRunMessageReceived?.Invoke(CommunicatorName, strReceiveMsg); // 触发运行事件 } catch { } try { MessageReceived?.Invoke(strReceiveMsg); // 触发消息接收事件 } catch { } } } catch { } } public void SendMessageToClient(TcpClient client, string message) { NetworkStream stream = client.GetStream(); byte[] messageBytes = Encoding.UTF8.GetBytes(message); stream.Write(messageBytes, 0, messageBytes.Length); stream.Flush(); } public override bool SendMessage(string message) { //空消息不发送 if (string.IsNullOrEmpty(message) || message.Trim() == "") return true; List listRemoveTcpClients = new List(); foreach (var client in _clients) { try { SendMessageToClient(client, message); } catch (Exception ex) { Debug.WriteLine($"发送消息到 {client.ToString()} 客户端时发生错误: {ex.Message}"); listRemoveTcpClients.Add(client); } } foreach (var offlineTcpClient in listRemoveTcpClients) { lock (_clients) { _clients.Remove(offlineTcpClient); } } return true; } } }