using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace WIDESEAWCS_Tasks.SocketServer { public partial class TcpSocketServer { /// /// ¼ìË÷µ±Ç°ÔÚ·þÎñÖÐ×¢²áµÄËùÓпͻ§¶Ë±êʶ·ûµÄÖ»¶ÁÁÐ±í¡£ /// /// ·µ»ØµÄÁбí±íʾµ÷ÓÃʱ¿Ì¿Í»§¶ËIDµÄ¿ìÕÕ¡£ºóÐø¶Ô¿Í»§¶Ë¼¯ºÏµÄ¸ü¸Ä²»»áÓ°Ïì·µ»ØµÄÁÐ±í¡£´Ë·½·¨ÊÇḬ̈߳²È«µÄ¡£ /// °üº¬¿Í»§¶ËIDµÄ¡£Èç¹ûûÓпͻ§¶Ë×¢²á£¬ÁÐ±í½«Îª¿Õ¡£ public IReadOnlyList GetClientIds() { lock (_syncRoot) { return _clients.Keys.ToList(); } } /// /// ¼ìË÷ÓëÖ¸¶¨É豸±êʶ·û¹ØÁªµÄ¿Í»§¶Ë±êʶ·û¡£ /// /// ´Ë·½·¨ÊÇḬ̈߳²È«µÄ¡£Èç¹ûδÕÒµ½É豸±êʶ·û£¬·½·¨½«·µ»Ønull¶ø²»ÊÇÅ׳öÒì³£¡£ /// Òª¼ìË÷¿Í»§¶Ë±êʶ·ûµÄÉ豸µÄΨһ±êʶ·û¡£²»ÄÜΪnull¡£ /// ÓëÖ¸¶¨É豸±êʶ·û¹ØÁªµÄ¿Í»§¶Ë±êʶ·û£¬Èç¹û²»´æÔÚ¹ØÁªÔò·µ»Ønull¡£ public string? GetClientIdByDevice(string deviceId) { lock (_syncRoot) { return _deviceBindings.TryGetValue(deviceId, out var cid) ? cid : null; } } /// /// Òì²½ÏòÖ¸¶¨É豸·¢ËÍÏûÏ¢¡£ /// /// Èç¹ûÖ¸¶¨É豸δע²á»òÎÞ·¨ÕÒµ½£¬Ôò·µ»Ø ¡£ /// Ä¿±êÉ豸µÄΨһ±êʶ·û¡£²»ÄÜΪnull»ò¿Õ¡£ /// Òª·¢Ë͸øÉ豸µÄÏûÏ¢¡£²»ÄÜΪnull¡£ /// ±íʾÒì²½²Ù×÷µÄÈÎÎñ¡£Èç¹ûÏûÏ¢³É¹¦·¢ËÍ£¬ÈÎÎñ½á¹ûΪ £» /// ·ñÔòΪ ¡£ public Task SendToDeviceAsync(string deviceId, string message) { var clientId = GetClientIdByDevice(deviceId); if (clientId == null) return Task.FromResult(false); return SendToClientAsync(clientId, message); } /// /// ͨ¹ýTCPÁ¬½ÓÒì²½ÏòÖ¸¶¨¿Í»§¶Ë·¢ËÍ´øÖ¡µÄÎı¾ÏûÏ¢¡£ /// /// Èç¹û¿Í»§¶ËδÁ¬½Ó»ò²»´æÔÚ£¬´Ë·½·¨½«·µ»Ø ÇÒ²»·¢ËÍÏûÏ¢¡£ /// ÏûÏ¢½«ÓÅÏÈʹÓÿͻ§¶ËÊ×Ñ¡µÄÎı¾±àÂë½øÐбàÂ룻·ñÔòʹÓÃĬÈϱàÂë¡£ /// ´Ë·½·¨¶ÔÓÚÏò²»Í¬¿Í»§¶ËµÄ²¢·¢µ÷ÓÃÊÇḬ̈߳²È«µÄ¡£ /// Òª·¢ËÍÏûÏ¢µ½µÄ¿Í»§¶ËµÄΨһ±êʶ·û¡£±ØÐë¶ÔÓ¦ÒÑÁ¬½ÓµÄ¿Í»§¶Ë¡£ /// Òª·¢Ë͸ø¿Í»§¶ËµÄÎı¾ÏûÏ¢¡£²»ÄÜΪnull¡£ /// ±íʾÒì²½²Ù×÷µÄÈÎÎñ¡£Èç¹ûÏûÏ¢³É¹¦·¢ËÍ£¬ÈÎÎñ½á¹ûΪ £» /// ·ñÔò£¬Èç¹û¿Í»§¶ËδÁ¬½Ó»ò²»´æÔÚ£¬½á¹ûΪ ¡£ public async Task SendToClientAsync(string clientId, string message) { TcpClient? client; SemaphoreSlim? sem = null; Encoding? enc = null; lock (_syncRoot) { _clients.TryGetValue(clientId, out client); _clientLocks.TryGetValue(clientId, out sem); _clientEncodings.TryGetValue(clientId, out enc); } if (client == null || !client.Connected) { return false; } enc ??= _textEncoding; if (sem != null) await sem.WaitAsync(); try { var ns = client.GetStream(); var framedMessage = BuildFramedMessage(message); var data = enc.GetBytes(framedMessage); await ns.WriteAsync(data, 0, data.Length); } finally { if (sem != null) sem.Release(); } return true; } /// /// Òì²½ÏòËùÓÐÒÑÁ¬½ÓµÄ¿Í»§¶Ë·¢ËÍÖ¸¶¨µÄÏûÏ¢¡£ /// /// Èç¹ûÏòij¸ö¿Í»§¶Ë·¢ËÍÏûϢʱ·¢Éú´íÎó£¬Òì³£½«±»ÒÖÖÆ²¢¼ÌÐøÏòÆäËû¿Í»§¶Ë¹ã²¥¡£ /// µ±ËùÓз¢ËͲÙ×÷Íê³Éºó£¬´Ë·½·¨½áÊø¡£ /// Òª¹ã²¥¸øËùÓпͻ§¶ËµÄÏûÏ¢¡£²»ÄÜΪnull¡£ /// ±íʾÒì²½¹ã²¥²Ù×÷µÄÈÎÎñ¡£ public async Task BroadcastAsync(string message) { List clients; lock (_syncRoot) { clients = _clients.Values.ToList(); } await Task.WhenAll(clients.Select(c => Task.Run(async () => { try { await SendMessageAsync(c, message); } catch { } }))); } /// /// ͨ¹ýÍøÂçÁ÷Òì²½ÏòÖ¸¶¨µÄTCP¿Í»§¶Ë·¢ËÍ´øÖ¡µÄÎı¾ÏûÏ¢¡£ /// /// Èç¹û¿Í»§¶ËΪnull»òδÁ¬½Ó£¬´Ë·½·¨½«Á¢¼´·µ»Ø¶ø²»·¢ËÍÏûÏ¢¡£ /// ÏûÏ¢½«Ê¹ÓÃÅäÖõÄÎı¾±àÂë½øÐбàÂë²¢Ìí¼ÓÖ¡Í·ºóͨ¹ýÍøÂçÁ÷·¢ËÍ¡£ /// Òª·¢ËÍÏûÏ¢µ½µÄTCP¿Í»§¶Ë¡£±ØÐë´¦ÓÚÁ¬½Ó״̬£»·ñÔò·½·¨²»Ö´ÐÐÈκβÙ×÷¡£ /// Òª·¢Ë͸ø¿Í»§¶ËµÄÎı¾ÏûÏ¢¡£ÏûÏ¢ÔÚ´«Êäǰ½«±»±àÂë²¢Ìí¼ÓÖ¡Í·¡£ /// ±íʾÒì²½·¢ËͲÙ×÷µÄÈÎÎñ¡£ private async Task SendMessageAsync(TcpClient client, string message) { if (client == null || !client.Connected) { return; } NetworkStream stream = client.GetStream(); var framedMessage = BuildFramedMessage(message); var data = _textEncoding.GetBytes(framedMessage); await stream.WriteAsync(data, 0, data.Length); } } }