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