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
|
{
|
/// <summary>
|
/// ¼ìË÷µ±Ç°ÔÚ·þÎñÖÐ×¢²áµÄËùÓпͻ§¶Ë±êʶ·ûµÄÖ»¶ÁÁÐ±í¡£
|
/// </summary>
|
/// <remarks>·µ»ØµÄÁбí±íʾµ÷ÓÃʱ¿Ì¿Í»§¶ËIDµÄ¿ìÕÕ¡£ºóÐø¶Ô¿Í»§¶Ë¼¯ºÏµÄ¸ü¸Ä²»»áÓ°Ïì·µ»ØµÄÁÐ±í¡£´Ë·½·¨ÊÇḬ̈߳²È«µÄ¡£</remarks>
|
/// <returns>°üº¬¿Í»§¶ËIDµÄ<see cref="IReadOnlyList{String}"/>¡£Èç¹ûûÓпͻ§¶Ë×¢²á£¬ÁÐ±í½«Îª¿Õ¡£</returns>
|
public IReadOnlyList<string> GetClientIds()
|
{
|
lock (_syncRoot)
|
{
|
return _clients.Keys.ToList();
|
}
|
}
|
|
/// <summary>
|
/// ¼ìË÷ÓëÖ¸¶¨É豸±êʶ·û¹ØÁªµÄ¿Í»§¶Ë±êʶ·û¡£
|
/// </summary>
|
/// <remarks>´Ë·½·¨ÊÇḬ̈߳²È«µÄ¡£Èç¹ûδÕÒµ½É豸±êʶ·û£¬·½·¨½«·µ»Ønull¶ø²»ÊÇÅ׳öÒì³£¡£</remarks>
|
/// <param name="deviceId">Òª¼ìË÷¿Í»§¶Ë±êʶ·ûµÄÉ豸µÄΨһ±êʶ·û¡£²»ÄÜΪnull¡£</param>
|
/// <returns>ÓëÖ¸¶¨É豸±êʶ·û¹ØÁªµÄ¿Í»§¶Ë±êʶ·û£¬Èç¹û²»´æÔÚ¹ØÁªÔò·µ»Ønull¡£</returns>
|
public string? GetClientIdByDevice(string deviceId)
|
{
|
lock (_syncRoot)
|
{
|
return _deviceBindings.TryGetValue(deviceId, out var cid) ? cid : null;
|
}
|
}
|
|
/// <summary>
|
/// Òì²½ÏòÖ¸¶¨É豸·¢ËÍÏûÏ¢¡£
|
/// </summary>
|
/// <remarks>Èç¹ûÖ¸¶¨É豸δע²á»òÎÞ·¨ÕÒµ½£¬Ôò·µ»Ø <see langword="false"/>¡£</remarks>
|
/// <param name="deviceId">Ä¿±êÉ豸µÄΨһ±êʶ·û¡£²»ÄÜΪnull»ò¿Õ¡£</param>
|
/// <param name="message">Òª·¢Ë͸øÉ豸µÄÏûÏ¢¡£²»ÄÜΪnull¡£</param>
|
/// <returns>±íʾÒì²½²Ù×÷µÄÈÎÎñ¡£Èç¹ûÏûÏ¢³É¹¦·¢ËÍ£¬ÈÎÎñ½á¹ûΪ <see langword="true"/>£»
|
/// ·ñÔòΪ <see langword="false"/>¡£</returns>
|
public Task<bool> SendToDeviceAsync(string deviceId, string message)
|
{
|
var clientId = GetClientIdByDevice(deviceId);
|
if (clientId == null) return Task.FromResult(false);
|
return SendToClientAsync(clientId, message);
|
}
|
|
/// <summary>
|
/// ͨ¹ýTCPÁ¬½ÓÒì²½ÏòÖ¸¶¨¿Í»§¶Ë·¢ËÍ´øÖ¡µÄÎı¾ÏûÏ¢¡£
|
/// </summary>
|
/// <remarks>Èç¹û¿Í»§¶ËδÁ¬½Ó»ò²»´æÔÚ£¬´Ë·½·¨½«·µ»Ø <see langword="false"/> ÇÒ²»·¢ËÍÏûÏ¢¡£
|
/// ÏûÏ¢½«ÓÅÏÈʹÓÿͻ§¶ËÊ×Ñ¡µÄÎı¾±àÂë½øÐбàÂ룻·ñÔòʹÓÃĬÈϱàÂë¡£
|
/// ´Ë·½·¨¶ÔÓÚÏò²»Í¬¿Í»§¶ËµÄ²¢·¢µ÷ÓÃÊÇḬ̈߳²È«µÄ¡£</remarks>
|
/// <param name="clientId">Òª·¢ËÍÏûÏ¢µ½µÄ¿Í»§¶ËµÄΨһ±êʶ·û¡£±ØÐë¶ÔÓ¦ÒÑÁ¬½ÓµÄ¿Í»§¶Ë¡£</param>
|
/// <param name="message">Òª·¢Ë͸ø¿Í»§¶ËµÄÎı¾ÏûÏ¢¡£²»ÄÜΪnull¡£</param>
|
/// <returns>±íʾÒì²½²Ù×÷µÄÈÎÎñ¡£Èç¹ûÏûÏ¢³É¹¦·¢ËÍ£¬ÈÎÎñ½á¹ûΪ <see langword="true"/>£»
|
/// ·ñÔò£¬Èç¹û¿Í»§¶ËδÁ¬½Ó»ò²»´æÔÚ£¬½á¹ûΪ <see langword="false"/>¡£</returns>
|
public async Task<bool> 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;
|
}
|
|
/// <summary>
|
/// Òì²½ÏòËùÓÐÒÑÁ¬½ÓµÄ¿Í»§¶Ë·¢ËÍÖ¸¶¨µÄÏûÏ¢¡£
|
/// </summary>
|
/// <remarks>Èç¹ûÏòij¸ö¿Í»§¶Ë·¢ËÍÏûϢʱ·¢Éú´íÎó£¬Òì³£½«±»ÒÖÖÆ²¢¼ÌÐøÏòÆäËû¿Í»§¶Ë¹ã²¥¡£
|
/// µ±ËùÓз¢ËͲÙ×÷Íê³Éºó£¬´Ë·½·¨½áÊø¡£</remarks>
|
/// <param name="message">Òª¹ã²¥¸øËùÓпͻ§¶ËµÄÏûÏ¢¡£²»ÄÜΪnull¡£</param>
|
/// <returns>±íʾÒì²½¹ã²¥²Ù×÷µÄÈÎÎñ¡£</returns>
|
public async Task BroadcastAsync(string message)
|
{
|
List<TcpClient> clients;
|
lock (_syncRoot)
|
{
|
clients = _clients.Values.ToList();
|
}
|
|
await Task.WhenAll(clients.Select(c => Task.Run(async () =>
|
{
|
try { await SendMessageAsync(c, message); } catch { }
|
})));
|
}
|
|
/// <summary>
|
/// ͨ¹ýÍøÂçÁ÷Òì²½ÏòÖ¸¶¨µÄTCP¿Í»§¶Ë·¢ËÍ´øÖ¡µÄÎı¾ÏûÏ¢¡£
|
/// </summary>
|
/// <remarks>Èç¹û¿Í»§¶ËΪnull»òδÁ¬½Ó£¬´Ë·½·¨½«Á¢¼´·µ»Ø¶ø²»·¢ËÍÏûÏ¢¡£
|
/// ÏûÏ¢½«Ê¹ÓÃÅäÖõÄÎı¾±àÂë½øÐбàÂë²¢Ìí¼ÓÖ¡Í·ºóͨ¹ýÍøÂçÁ÷·¢ËÍ¡£</remarks>
|
/// <param name="client">Òª·¢ËÍÏûÏ¢µ½µÄTCP¿Í»§¶Ë¡£±ØÐë´¦ÓÚÁ¬½Ó״̬£»·ñÔò·½·¨²»Ö´ÐÐÈκβÙ×÷¡£</param>
|
/// <param name="message">Òª·¢Ë͸ø¿Í»§¶ËµÄÎı¾ÏûÏ¢¡£ÏûÏ¢ÔÚ´«Êäǰ½«±»±àÂë²¢Ìí¼ÓÖ¡Í·¡£</param>
|
/// <returns>±íʾÒì²½·¢ËͲÙ×÷µÄÈÎÎñ¡£</returns>
|
public 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);
|
}
|
}
|
}
|