wanshenmean
2026-03-26 8e42d0c1b7ae36cff2e7c69999117911a4b6f300
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Clients.cs
@@ -9,6 +9,14 @@
{
    public partial class TcpSocketServer
    {
        /// <summary>
        /// 获取所有已连接客户端 ID 列表
        /// </summary>
        /// <remarks>
        /// 返回当前在服务器注册的客户端标识列表。
        /// 这是一个只读列表的快照,线程安全。
        /// </remarks>
        /// <returns>客户端 ID 列表</returns>
        public IReadOnlyList<string> GetClientIds()
        {
            lock (_syncRoot)
@@ -17,6 +25,14 @@
            }
        }
        /// <summary>
        /// 根据设备 ID 获取客户端 ID
        /// </summary>
        /// <remarks>
        /// 在设备绑定表中查找对应的客户端 ID。
        /// </remarks>
        /// <param name="deviceId">设备唯一标识</param>
        /// <returns>客户端 ID,如果未找到则返回 null</returns>
        public string? GetClientIdByDevice(string deviceId)
        {
            lock (_syncRoot)
@@ -25,6 +41,16 @@
            }
        }
        /// <summary>
        /// 异步向指定设备发送消息
        /// </summary>
        /// <remarks>
        /// 通过设备 ID 查找对应的客户端连接,然后发送消息。
        /// 如果设备未注册或连接不存在,返回 false。
        /// </remarks>
        /// <param name="deviceId">目标设备唯一标识</param>
        /// <param name="message">要发送的消息</param>
        /// <returns>发送是否成功</returns>
        public Task<bool> SendToDeviceAsync(string deviceId, string message)
        {
            var clientId = GetClientIdByDevice(deviceId);
@@ -32,6 +58,17 @@
            return SendToClientAsync(clientId, message);
        }
        /// <summary>
        /// 异步向指定客户端发送消息
        /// </summary>
        /// <remarks>
        /// 使用帧格式发送消息(添加头尾标识)。
        /// 每个客户端的发送操作是互斥的(通过信号量实现)。
        /// 如果客户端未连接或不存在,发送失败返回 false。
        /// </remarks>
        /// <param name="clientId">目标客户端 ID</param>
        /// <param name="message">要发送的消息</param>
        /// <returns>发送是否成功</returns>
        public async Task<bool> SendToClientAsync(string clientId, string message)
        {
            TcpClient? client;
@@ -51,11 +88,14 @@
            enc ??= _textEncoding;
            // 获取客户端发送锁
            if (sem != null) await sem.WaitAsync();
            try
            {
                // 发送消息
                var ns = client.GetStream();
                var data = enc.GetBytes((message ?? string.Empty) + "\n");
                var framedMessage = BuildFramedMessage(message);
                var data = enc.GetBytes(framedMessage);
                await ns.WriteAsync(data, 0, data.Length);
            }
            finally
@@ -65,6 +105,14 @@
            return true;
        }
        /// <summary>
        /// 异步广播消息到所有客户端
        /// </summary>
        /// <remarks>
        /// 将消息发送给所有已连接的客户端。
        /// 如果某个客户端发送失败,不影响其他客户端的发送。
        /// </remarks>
        /// <param name="message">要广播的消息</param>
        public async Task BroadcastAsync(string message)
        {
            List<TcpClient> clients;
@@ -73,13 +121,23 @@
                clients = _clients.Values.ToList();
            }
            // 并行发送消息到所有客户端
            await Task.WhenAll(clients.Select(c => Task.Run(async () =>
            {
                try { await SendAsync(c, message); } catch { }
                try { await SendMessageAsync(c, message); } catch { }
            })));
        }
        public static async Task SendAsync(TcpClient client, string message)
        /// <summary>
        /// 通过 NetworkStream 发送消息
        /// </summary>
        /// <remarks>
        /// 直接使用 TcpClient 的 NetworkStream 发送消息。
        /// 消息会添加帧头帧尾。
        /// </remarks>
        /// <param name="client">TCP 客户端</param>
        /// <param name="message">消息内容</param>
        public async Task SendMessageAsync(TcpClient client, string message)
        {
            if (client == null || !client.Connected)
            {
@@ -87,7 +145,8 @@
            }
            NetworkStream stream = client.GetStream();
            var data = Encoding.UTF8.GetBytes((message ?? string.Empty) + "\n");
            var framedMessage = BuildFramedMessage(message);
            var data = _textEncoding.GetBytes(framedMessage);
            await stream.WriteAsync(data, 0, data.Length);
        }
    }