//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在RRQMCore.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 // 交流QQ群:234762506 // 感谢您的下载和使用 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ using RRQMCore.ByteManager; using RRQMCore.Exceptions; using RRQMCore.Helper; using RRQMCore.Run; using RRQMCore.XREF.Newtonsoft.Json; using RRQMCore.XREF.Newtonsoft.Json.Linq; using RRQMSocket.Http; using RRQMSocket.RPC.RRQMRPC; using System; using System.Text; namespace RRQMSocket.RPC.JsonRpc { /// /// JsonRpc客户端 /// public class JsonRpcClient : TcpClient, IJsonRpcClient { private int maxPackageSize; private JsonRpcProtocolType protocolType; private RRQMWaitHandle waitHandle; /// /// 构造函数 /// public JsonRpcClient() { waitHandle = new RRQMWaitHandle(); } /// /// 最大数据包长度 /// public int MaxPackageSize { get { return maxPackageSize; } } /// /// 协议类型 /// public JsonRpcProtocolType ProtocolType { get { return protocolType; } } /// /// RPC调用 /// /// 方法名 /// 调用配置 /// 参数 /// /// /// /// /// public T Invoke(string method, InvokeOption invokeOption, ref object[] parameters, Type[] types) { JsonRpcWaitContext context = new JsonRpcWaitContext(); WaitData waitData = this.waitHandle.GetWaitData(context); ByteBlock byteBlock = this.BytePool.GetByteBlock(this.BufferLength); if (invokeOption == null) { invokeOption = InvokeOption.WaitInvoke; } try { JObject jobject = new JObject(); jobject.Add("jsonrpc", JToken.FromObject("2.0")); jobject.Add("method", JToken.FromObject(method)); jobject.Add("params", JToken.FromObject(parameters)); if (invokeOption.FeedbackType == FeedbackType.WaitInvoke) { jobject.Add("id", JToken.FromObject(context.Sign.ToString())); } else { jobject.Add("id", null); } switch (this.protocolType) { case JsonRpcProtocolType.Tcp: { byteBlock.Write(Encoding.UTF8.GetBytes(jobject.ToString(Formatting.None))); break; } case JsonRpcProtocolType.Http: { HttpRequest httpRequest = new HttpRequest(); httpRequest.Method = "POST"; httpRequest.FromJson(jobject.ToString(Formatting.None)); httpRequest.Build(byteBlock); } break; } switch (invokeOption.FeedbackType) { case FeedbackType.OnlySend: { this.SendAsync(byteBlock); } break; case FeedbackType.WaitSend: case FeedbackType.WaitInvoke: { this.Send(byteBlock); } break; default: break; } } catch (Exception ex) { throw ex; } finally { byteBlock.Dispose(); } switch (invokeOption.FeedbackType) { case FeedbackType.OnlySend: case FeedbackType.WaitSend: { this.waitHandle.Destroy(waitData); return default; } case FeedbackType.WaitInvoke: { waitData.Wait(invokeOption.Timeout); JsonRpcWaitContext resultContext = (JsonRpcWaitContext)waitData.WaitResult; this.waitHandle.Destroy(waitData); if (resultContext.Status == 0) { throw new RRQMTimeoutException("等待结果超时"); } if (resultContext.error != null) { throw new RRQMRPCException(resultContext.error.message); } try { if (typeof(T).IsPrimitive || typeof(T) == typeof(string)) { return (T)resultContext.Return.ToString().ParseToType(typeof(T)); } return JsonConvert.DeserializeObject(resultContext.Return.ToString()); } catch (Exception ex) { throw ex; } } default: return default; } } /// /// RPC调用 /// /// 方法名 /// 调用配置 /// 参数 /// /// /// /// public void Invoke(string method, InvokeOption invokeOption, ref object[] parameters, Type[] types) { JsonRpcWaitContext context = new JsonRpcWaitContext(); WaitData waitData = this.waitHandle.GetWaitData(context); ByteBlock byteBlock = this.BytePool.GetByteBlock(this.BufferLength); if (invokeOption == null) { invokeOption = InvokeOption.WaitInvoke; } try { JObject jobject = new JObject(); jobject.Add("jsonrpc", JToken.FromObject("2.0")); jobject.Add("method", JToken.FromObject(method)); jobject.Add("params", JToken.FromObject(parameters)); if (invokeOption.FeedbackType == FeedbackType.WaitInvoke) { jobject.Add("id", JToken.FromObject(context.Sign.ToString())); } else { jobject.Add("id", null); } switch (this.protocolType) { case JsonRpcProtocolType.Tcp: { byteBlock.Write(Encoding.UTF8.GetBytes(jobject.ToString(Formatting.None))); break; } case JsonRpcProtocolType.Http: { HttpRequest httpRequest = new HttpRequest(); httpRequest.Method = "POST"; httpRequest.FromJson(jobject.ToString(Formatting.None)); httpRequest.Build(byteBlock); } break; } switch (invokeOption.FeedbackType) { case FeedbackType.OnlySend: { this.SendAsync(byteBlock); } break; case FeedbackType.WaitSend: case FeedbackType.WaitInvoke: { this.Send(byteBlock); } break; default: break; } } catch (Exception ex) { throw ex; } finally { byteBlock.Dispose(); } switch (invokeOption.FeedbackType) { case FeedbackType.OnlySend: case FeedbackType.WaitSend: { this.waitHandle.Destroy(waitData); return; } case FeedbackType.WaitInvoke: { waitData.Wait(invokeOption.Timeout); JsonRpcWaitContext resultContext = (JsonRpcWaitContext)waitData.WaitResult; this.waitHandle.Destroy(waitData); if (resultContext.Status == 0) { throw new RRQMTimeoutException("等待结果超时"); } if (resultContext.error != null) { throw new RRQMRPCException(resultContext.error.message); } return; } default: return; } } /// /// RPC调用 /// /// 方法名 /// 调用配置 /// 参数 /// /// /// public void Invoke(string method, InvokeOption invokeOption, params object[] parameters) { this.Invoke(method, invokeOption, ref parameters, null); } /// /// RPC调用 /// /// 方法名 /// 调用配置 /// 参数 /// /// /// /// public T Invoke(string method, InvokeOption invokeOption, params object[] parameters) { return this.Invoke(method, invokeOption, ref parameters, null); } /// /// 处理数据 /// /// /// protected override void HandleReceivedData(ByteBlock byteBlock, object obj) { switch (this.protocolType) { case JsonRpcProtocolType.Tcp: { string jsonString = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len); JsonResponseContext responseContext = (JsonResponseContext)JsonConvert.DeserializeObject(jsonString, typeof(JsonResponseContext)); if (responseContext != null) { JsonRpcWaitContext waitContext = new JsonRpcWaitContext(); waitContext.Status = 1; waitContext.Sign = int.Parse(responseContext.id); waitContext.error = responseContext.error; waitContext.Return = responseContext.result; this.waitHandle.SetRun(waitContext); } break; } case JsonRpcProtocolType.Http: { HttpResponse httpResponse = (HttpResponse)obj; JsonResponseContext responseContext = (JsonResponseContext)JsonConvert.DeserializeObject(httpResponse.Body, typeof(JsonResponseContext)); if (responseContext != null) { JsonRpcWaitContext waitContext = new JsonRpcWaitContext(); waitContext.Status = 1; waitContext.Sign = int.Parse(responseContext.id); waitContext.error = responseContext.error; waitContext.Return = responseContext.result; this.waitHandle.SetRun(waitContext); } break; } } } /// /// 载入配置 /// /// protected override void LoadConfig(TcpClientConfig clientConfig) { base.LoadConfig(clientConfig); this.maxPackageSize = (int)clientConfig.GetValue(JsonRpcClientConfig.MaxPackageSizeProperty); this.protocolType = (JsonRpcProtocolType)clientConfig.GetValue(JsonRpcClientConfig.ProtocolTypeProperty); switch (this.protocolType) { case JsonRpcProtocolType.Tcp: base.SetDataHandlingAdapter(new TerminatorDataHandlingAdapter(this.maxPackageSize, "\r\n")); break; case JsonRpcProtocolType.Http: base.SetDataHandlingAdapter(new HttpDataHandlingAdapter(this.maxPackageSize, HttpType.Client)); break; } } } }