//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在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.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; using TouchSocket.Core; using TouchSocket.Sockets; namespace TouchSocket.Rpc.TouchRpc { /// /// TcpTouchRpcClient /// public partial class TcpTouchRpcClient : TcpClientBase, ITcpTouchRpcClient { private readonly ActionMap m_actionMap; private readonly RpcActor m_rpcActor; private RpcStore m_rpcStore; /// /// 创建一个TcpTouchRpcClient实例。 /// public TcpTouchRpcClient() { m_actionMap = new ActionMap(); m_rpcActor = new RpcActor(false) { OutputSend = RpcActorSend, OnRouting = OnRpcActorRouting, OnHandshaked = OnRpcActorHandshaked, OnReceived = OnRpcActorReceived, OnClose = OnRpcServiceClose, GetInvokeMethod = GetInvokeMethod, OnStreamTransfering = OnRpcActorStreamTransfering, OnStreamTransfered = OnRpcActorStreamTransfered, OnFileTransfering = OnRpcActorFileTransfering, OnFileTransfered = OnRpcActorFileTransfered, Caller = this }; } /// /// 方法映射表 /// public ActionMap ActionMap { get => m_actionMap; } /// public string ID => m_rpcActor.ID; /// public bool IsHandshaked => m_rpcActor == null ? false : m_rpcActor.IsHandshaked; /// public string RootPath { get => m_rpcActor.RootPath; set => m_rpcActor.RootPath = value; } /// public RpcActor RpcActor => m_rpcActor; /// public RpcStore RpcStore => m_rpcStore; /// public SerializationSelector SerializationSelector => m_rpcActor.SerializationSelector; /// public Func TryCanInvoke { get; set; } /// public bool ChannelExisted(int id) { return m_rpcActor.ChannelExisted(id); } /// /// 建立Tcp连接,并且执行握手。 /// /// /// public override ITcpClient Connect(int timeout = 5000) { lock (SyncRoot) { if (IsHandshaked) { return this; } if (!Online) { base.Connect(timeout); } m_rpcActor.Handshake(Config.GetValue(TouchRpcConfigExtensions.VerifyTokenProperty), Config.GetValue(TouchRpcConfigExtensions.DefaultIdProperty), default, timeout, Config.GetValue(TouchRpcConfigExtensions.MetadataProperty)); return this; } } /// public Channel CreateChannel() { return m_rpcActor.CreateChannel(); } /// public Channel CreateChannel(int id) { return m_rpcActor.CreateChannel(id); } /// public Channel CreateChannel(string targetId) { return m_rpcActor.CreateChannel(targetId); } /// public Channel CreateChannel(string targetId, int id) { return m_rpcActor.CreateChannel(targetId, id); } /// public void Invoke(string method, IInvokeOption invokeOption, params object[] parameters) { m_rpcActor.Invoke(method, invokeOption, parameters); } /// public T Invoke(string method, IInvokeOption invokeOption, params object[] parameters) { return m_rpcActor.Invoke(method, invokeOption, parameters); } /// public void Invoke(string targetId, string method, IInvokeOption invokeOption, ref object[] parameters, Type[] types) { m_rpcActor.Invoke(targetId, method, invokeOption, ref parameters, types); } /// public T Invoke(string targetId, string method, IInvokeOption invokeOption, ref object[] parameters, Type[] types) { return m_rpcActor.Invoke(targetId, method, invokeOption, ref parameters, types); } /// public T Invoke(string method, IInvokeOption invokeOption, ref object[] parameters, Type[] types) { return m_rpcActor.Invoke(method, invokeOption, ref parameters, types); } /// public void Invoke(string method, IInvokeOption invokeOption, ref object[] parameters, Type[] types) { m_rpcActor.Invoke(method, invokeOption, ref parameters, types); } /// public void Invoke(string id, string method, IInvokeOption invokeOption, params object[] parameters) { m_rpcActor.Invoke(id, method, invokeOption, parameters); } /// public T Invoke(string id, string method, IInvokeOption invokeOption, params object[] parameters) { return m_rpcActor.Invoke(id, method, invokeOption, parameters); } /// public Task InvokeAsync(string method, IInvokeOption invokeOption, params object[] parameters) { return m_rpcActor.InvokeAsync(method, invokeOption, parameters); } /// public Task InvokeAsync(string method, IInvokeOption invokeOption, params object[] parameters) { return m_rpcActor.InvokeAsync(method, invokeOption, parameters); } /// public Task InvokeAsync(string id, string method, IInvokeOption invokeOption, params object[] parameters) { return m_rpcActor.InvokeAsync(id, method, invokeOption, parameters); } /// public Task InvokeAsync(string id, string method, IInvokeOption invokeOption, params object[] parameters) { return m_rpcActor.InvokeAsync(id, method, invokeOption, parameters); } /// public bool Ping(int timeout = 5000) { return m_rpcActor.Ping(timeout); } /// public bool Ping(string targetId, int timeout = 5000) { return m_rpcActor.Ping(targetId, timeout); } /// public Result PullFile(FileOperator fileOperator) { return m_rpcActor.PullFile(fileOperator); } /// public Result PullFile(string targetId, FileOperator fileOperator) { return m_rpcActor.PullFile(targetId, fileOperator); } /// public Task PullFileAsync(FileOperator fileOperator) { return m_rpcActor.PullFileAsync(fileOperator); } /// public Task PullFileAsync(string targetId, FileOperator fileOperator) { return m_rpcActor.PullFileAsync(targetId, fileOperator); } /// public Result PushFile(FileOperator fileOperator) { return m_rpcActor.PushFile(fileOperator); } /// public Result PushFile(string targetId, FileOperator fileOperator) { return m_rpcActor.PushFile(targetId, fileOperator); } /// public Task PushFileAsync(FileOperator fileOperator) { return m_rpcActor.PushFileAsync(fileOperator); } /// public Task PushFileAsync(string targetId, FileOperator fileOperator) { return m_rpcActor.PushFileAsync(targetId, fileOperator); } /// public void ResetID(string id) { m_rpcActor.ResetID(id); } #region 发送 /// public void Send(short protocol, byte[] buffer, int offset, int length) { m_rpcActor.Send(protocol, buffer, offset, length); } /// /// 不允许直接发送 /// /// /// /// public override void Send(byte[] buffer, int offset, int length) { throw new Exception("不允许直接发送,请指定任意大于0的协议,然后发送。"); } /// /// 不允许直接发送 /// /// public override void Send(IList> transferBytes) { throw new Exception("不允许直接发送,请指定任意大于0的协议,然后发送。"); } /// public Task SendAsync(short protocol, byte[] buffer, int offset, int length) { return m_rpcActor.SendAsync(protocol, buffer, offset, length); } /// /// 不允许直接发送 /// /// /// /// public override Task SendAsync(byte[] buffer, int offset, int length) { throw new Exception("不允许直接发送,请指定任意大于0的协议,然后发送。"); } /// /// 不允许直接发送 /// /// public override Task SendAsync(IList> transferBytes) { throw new Exception("不允许直接发送,请指定任意大于0的协议,然后发送。"); } #endregion 发送 /// public Result SendStream(Stream stream, StreamOperator streamOperator, Metadata metadata = null) { return m_rpcActor.SendStream(stream, streamOperator, metadata); } /// public Task SendStreamAsync(Stream stream, StreamOperator streamOperator, Metadata metadata = null) { return m_rpcActor.SendStreamAsync(stream, streamOperator, metadata); } /// public bool TrySubscribeChannel(int id, out Channel channel) { return m_rpcActor.TrySubscribeChannel(id, out channel); } #region 小文件 /// public PullSmallFileResult PullSmallFile(string targetId, string path, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) { return m_rpcActor.PullSmallFile(targetId, path, metadata, timeout, token); } /// public PullSmallFileResult PullSmallFile(string path, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) { return m_rpcActor.PullSmallFile(path, metadata, timeout, token); } /// public Task PullSmallFileAsync(string targetId, string path, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) { return m_rpcActor.PullSmallFileAsync(targetId, path, metadata, timeout, token); } /// public Task PullSmallFileAsync(string path, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) { return m_rpcActor.PullSmallFileAsync(path, metadata, timeout, token); } /// public Result PushSmallFile(string targetId, string savePath, FileInfo fileInfo, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) { return m_rpcActor.PushSmallFile(targetId, savePath, fileInfo, metadata, timeout, token); } /// public Result PushSmallFile(string savePath, FileInfo fileInfo, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) { return m_rpcActor.PushSmallFile(savePath, fileInfo, metadata, timeout, token); } /// public Task PushSmallFileAsync(string targetId, string savePath, FileInfo fileInfo, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) { return m_rpcActor.PushSmallFileAsync(targetId, savePath, fileInfo, metadata, timeout, token); } /// public Task PushSmallFileAsync(string savePath, FileInfo fileInfo, Metadata metadata = null, int timeout = 5000, CancellationToken token = default) { return m_rpcActor.PushSmallFileAsync(savePath, fileInfo, metadata, timeout, token); } #endregion 小文件 /// protected override void Dispose(bool disposing) { m_rpcActor.SafeDispose(); base.Dispose(disposing); } /// protected override void HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo) { m_rpcActor.InputReceivedData(byteBlock); } /// protected override void LoadConfig(TouchSocketConfig config) { base.LoadConfig(config); RootPath = config.GetValue(TouchRpcConfigExtensions.RootPathProperty); m_rpcActor.SerializationSelector = config.GetValue(TouchRpcConfigExtensions.SerializationSelectorProperty); m_rpcActor.Logger = Container.Resolve(); m_rpcActor.FileController = Container.GetFileResourceController(); if (config.GetValue(RpcConfigExtensions.RpcStoreProperty) is RpcStore rpcStore) { rpcStore.AddRpcParser(GetType().Name, this); } else { new RpcStore(config.Container).AddRpcParser(GetType().Name, this); } this.SwitchProtocolToTouchRpc(); } /// protected override void OnConnecting(ConnectingEventArgs e) { SetDataHandlingAdapter(new FixedHeaderPackageAdapter()); base.OnConnecting(e); } /// protected override void OnDisconnected(DisconnectEventArgs e) { m_rpcActor.Close(e.Message); base.OnDisconnected(e); } #region 内部委托绑定 private MethodInstance GetInvokeMethod(string arg) { return m_actionMap.GetMethodInstance(arg); } private void OnRpcActorFileTransfered(RpcActor actor, FileTransferStatusEventArgs e) { if (UsePlugin && PluginsManager.Raise(nameof(ITouchRpcPlugin.OnFileTransfered), this, e)) { return; } OnFileTransfered(e); } private void OnRpcActorFileTransfering(RpcActor actor, FileOperationEventArgs e) { if (UsePlugin && PluginsManager.Raise(nameof(ITouchRpcPlugin.OnFileTransfering), this, e)) { return; } OnFileTransfering(e); } private void OnRpcActorHandshaked(RpcActor actor, VerifyOptionEventArgs e) { if (UsePlugin && PluginsManager.Raise(nameof(ITouchRpcPlugin.OnHandshaked), this, e)) { return; } OnHandshaked(e); } private void OnRpcActorReceived(RpcActor actor, short protocol, ByteBlock byteBlock) { if (UsePlugin && PluginsManager.Raise(nameof(ITouchRpcPlugin.OnReceivedProtocolData), this, new ProtocolDataEventArgs(protocol, byteBlock))) { return; } OnReceived(protocol, byteBlock); } private void OnRpcActorRouting(RpcActor actor, PackageRouterEventArgs e) { if (UsePlugin && PluginsManager.Raise(nameof(ITouchRpcPlugin.OnRouting), this, e)) { return; } OnRouting(e); } private void OnRpcActorStreamTransfered(RpcActor actor, StreamStatusEventArgs e) { if (UsePlugin && PluginsManager.Raise(nameof(ITouchRpcPlugin.OnStreamTransfered), this, e)) { return; } OnStreamTransfered(e); } private void OnRpcActorStreamTransfering(RpcActor actor, StreamOperationEventArgs e) { if (UsePlugin && PluginsManager.Raise(nameof(ITouchRpcPlugin.OnStreamTransfering), this, e)) { return; } OnStreamTransfering(e); } private void OnRpcServiceClose(RpcActor actor, string arg2) { Close(arg2); } private void RpcActorSend(RpcActor actor, ArraySegment[] transferBytes) { base.Send(transferBytes); } #endregion 内部委托绑定 #region RPC解析器 void IRpcParser.OnRegisterServer(MethodInstance[] methodInstances) { foreach (var methodInstance in methodInstances) { if (methodInstance.GetAttribute() is TouchRpcAttribute attribute) { ActionMap.Add(attribute.GetInvokenKey(methodInstance), methodInstance); } } } void IRpcParser.OnUnregisterServer(MethodInstance[] methodInstances) { foreach (var methodInstance in methodInstances) { if (methodInstance.GetAttribute() is TouchRpcAttribute attribute) { m_actionMap.Remove(attribute.GetInvokenKey(methodInstance)); } } } void IRpcParser.SetRpcStore(RpcStore rpcStore) { m_rpcActor.RpcStore = rpcStore; m_rpcStore = rpcStore; } #endregion RPC解析器 #region 事件触发 /// /// 当文件传输结束之后。并不意味着完成传输,请通过属性值进行判断。 /// /// protected virtual void OnFileTransfered(FileTransferStatusEventArgs e) { } /// /// 在文件传输即将进行时触发。 /// /// protected virtual void OnFileTransfering(FileOperationEventArgs e) { } /// /// 在完成握手连接时 /// /// protected virtual void OnHandshaked(VerifyOptionEventArgs e) { } /// /// 收到数据。 /// /// /// protected virtual void OnReceived(short protocol, ByteBlock byteBlock) { } /// /// 当需要转发路由包时 /// /// protected virtual void OnRouting(PackageRouterEventArgs e) { } /// /// 流数据处理,用户需要在此事件中对e.Bucket手动释放。 /// /// protected virtual void OnStreamTransfered(StreamStatusEventArgs e) { } /// /// 即将接收流数据,用户需要在此事件中对e.Bucket初始化。 /// /// protected virtual void OnStreamTransfering(StreamOperationEventArgs e) { } #endregion 事件触发 } }