//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 // 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 // CSDN博客:https://blog.csdn.net/qq_40374647 // 哔哩哔哩视频:https://space.bilibili.com/94253567 // Gitee源代码仓库:https://gitee.com/RRQM_Home // Github源代码仓库:https://github.com/RRQM // API首页:https://www.yuque.com/rrqm/touchsocket/index // 交流QQ群:234762506 // 感谢您的下载和使用 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ using System; using System.Collections.Concurrent; using TouchSocket.Core; using TouchSocket.Resources; using TouchSocket.Sockets; namespace TouchSocket.Rpc.TouchRpc { public partial class RpcActor { private readonly ConcurrentDictionary m_userChannels; /// /// /// /// /// public bool ChannelExisted(int id) { return m_userChannels.ContainsKey(id); } /// public Channel CreateChannel() { return this.PrivateCreateChannel(default, true); } /// public Channel CreateChannel(int id) { return this.PrivateCreateChannel(default, false, id); } /// public Channel CreateChannel(string targetId, int id) { if (string.IsNullOrEmpty(targetId)) { throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId)); } if (IsService) { if (this.TryFindRpcActor(targetId, out RpcActor actor)) { return actor.CreateChannel(id); } throw new ClientNotFindException(TouchSocketStatus.ClientNotFind.GetDescription()); } return this.PrivateCreateChannel(targetId, false, id); } private Channel PrivateCreateChannel(string targetId, bool random, int id = 0) { lock (SyncRoot) { if (random) { id = new object().GetHashCode(); } else { if (ChannelExisted(id)) { throw new Exception(TouchSocketStatus.ChannelExisted.GetDescription(id)); } } ByteBlock byteBlock = new ByteBlock(); WaitCreateChannelPackage waitCreateChannel = new WaitCreateChannelPackage() { Random = random, ChannelID = id, SourceId = this.ID, TargetId = targetId, Route = targetId.HasValue() }; WaitData waitData = WaitHandlePool.GetWaitData(waitCreateChannel); try { waitCreateChannel.Package(byteBlock); Send(TouchRpcUtility.P_100_CreateChannel_Request, byteBlock); switch (waitData.Wait(10 * 1000)) { case WaitDataStatus.SetRunning: { WaitCreateChannelPackage result = (WaitCreateChannelPackage)waitData.WaitResult; switch (result.Status.ToStatus()) { case TouchSocketStatus.Success: { InternalChannel channel = new InternalChannel(this, targetId); channel.SetID(result.ChannelID); channel.SetUsing(); if (m_userChannels.TryAdd(result.ChannelID, channel)) { return channel; } throw new Exception(TouchSocketStatus.UnknownError.GetDescription()); } case TouchSocketStatus.ClientNotFind: { throw new Exception(TouchSocketStatus.ClientNotFind.GetDescription(targetId)); } case TouchSocketStatus.RoutingNotAllowed: default: { throw new Exception(result.Status.ToStatus().GetDescription(result.Message)); } } } case WaitDataStatus.Overtime: { throw new TimeoutException(TouchSocketStatus.Overtime.GetDescription()); } default: { throw new Exception(TouchSocketStatus.UnknownError.GetDescription()); } } } finally { WaitHandlePool.Destroy(waitData); byteBlock.Dispose(); } } } internal void SendChannelPackage(ChannelPackage channelPackage) { using (ByteBlock byteBlock = new ByteBlock(channelPackage.GetLen())) { channelPackage.Package(byteBlock); this.Send(TouchRpcUtility.P_101_ChannelPackage, byteBlock); } } /// public Channel CreateChannel(string targetId) { if (string.IsNullOrEmpty(targetId)) { throw new ArgumentException($"“{nameof(targetId)}”不能为 null 或空。", nameof(targetId)); } if (IsService) { if (this.TryFindRpcActor(targetId, out RpcActor actor)) { return actor.CreateChannel(); } throw new ClientNotFindException(TouchSocketStatus.ClientNotFind.GetDescription()); } return this.PrivateCreateChannel(targetId, true); } internal bool RemoveChannel(int id) { return m_userChannels.TryRemove(id, out _); } /// /// 订阅通道 /// /// /// /// public bool TrySubscribeChannel(int id, out Channel channel) { if (m_userChannels.TryGetValue(id, out InternalChannel channelOut)) { if (channelOut.Using) { channel = null; return false; } channelOut.SetUsing(); channel = channelOut; return true; } channel = null; return false; } private bool QueueChannelPackage(ChannelPackage channelPackage) { if (m_userChannels.TryGetValue(channelPackage.ChannelId, out InternalChannel channel)) { channel.ReceivedData(channelPackage); return true; } return false; } private bool RequestCreateChannel(int id, string targetId) { lock (SyncRoot) { InternalChannel channel = new InternalChannel(this, targetId); channel.SetID(id); if (m_userChannels.TryAdd(id, channel)) { return true; } else { channel.SafeDispose(); return false; } } } } }