diff --git a/RRQMSocket.RPC.JsonRpc/Attribute/JsonRpcAttribute.cs b/RRQMSocket.RPC.JsonRpc/Attribute/JsonRpcAttribute.cs new file mode 100644 index 000000000..9cca23392 --- /dev/null +++ b/RRQMSocket.RPC.JsonRpc/Attribute/JsonRpcAttribute.cs @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------ +// 此代码版权归作者本人若汝棋茗所有 +// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按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 System; + +namespace RRQMSocket.RPC.JsonRpc +{ + /// + /// 适用于XmlRpc的标记 + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public sealed class JsonRpcAttribute : RPCMethodAttribute + { + /// + /// 构造函数 + /// + public JsonRpcAttribute() + { + } + + /// + /// 构造函数 + /// + /// + public JsonRpcAttribute(string methodKey) + { + this.MethodKey = methodKey; + } + + /// + /// 服务唯一标识 + /// + public string MethodKey { get; private set; } + } +} \ No newline at end of file diff --git a/RRQMSocket.RPC.JsonRpc/Control/ActionMap.cs b/RRQMSocket.RPC.JsonRpc/Control/ActionMap.cs new file mode 100644 index 000000000..81a9fb83d --- /dev/null +++ b/RRQMSocket.RPC.JsonRpc/Control/ActionMap.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// 此代码版权归作者本人若汝棋茗所有 +// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按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 System.Collections; +using System.Collections.Generic; + +namespace RRQMSocket.RPC.JsonRpc +{ + /// + /// 服务映射图 + /// + public class ActionMap: IEnumerable> + { + internal ActionMap() + { + this.actionMap = new Dictionary(); + } + + private Dictionary actionMap; + + internal void Add(string actionKey, MethodInstance methodInstance) + { + this.actionMap.Add(actionKey, methodInstance); + } + + /// + /// 服务键集合 + /// + public IEnumerable ActionKeys { get { return this.actionMap.Keys; } } + + /// + /// 通过routeUrl获取函数实例 + /// + /// + /// + /// + public bool TryGet(string actionKey, out MethodInstance methodInstance) + { + if (this.actionMap.ContainsKey(actionKey)) + { + methodInstance = this.actionMap[actionKey]; + return true; + } + methodInstance = null; + return false; + } + + /// + /// 返回迭代器 + /// + /// + public IEnumerator> GetEnumerator() + { + return this.actionMap.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.actionMap.GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/RRQMSocket.RPC.JsonRpc/Control/RpcRequestContext.cs b/RRQMSocket.RPC.JsonRpc/Control/RpcRequestContext.cs new file mode 100644 index 000000000..29eb52f02 --- /dev/null +++ b/RRQMSocket.RPC.JsonRpc/Control/RpcRequestContext.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RRQMSocket.RPC.JsonRpc +{ + /// + /// JsonRpc调用器 + /// + public class RpcRequestContext + { +#pragma warning disable CS1591 + public string jsonrpc; + public string method; + public object[] @params; + public string id; +#pragma warning restore CS1591 + } +} diff --git a/RRQMSocket.Json/LICENSE b/RRQMSocket.RPC.JsonRpc/LICENSE similarity index 100% rename from RRQMSocket.Json/LICENSE rename to RRQMSocket.RPC.JsonRpc/LICENSE diff --git a/RRQMSocket.RPC.JsonRpc/Parser/JsonRpcParser.cs b/RRQMSocket.RPC.JsonRpc/Parser/JsonRpcParser.cs new file mode 100644 index 000000000..60a4294a3 --- /dev/null +++ b/RRQMSocket.RPC.JsonRpc/Parser/JsonRpcParser.cs @@ -0,0 +1,245 @@ +//------------------------------------------------------------------------------ +// 此代码版权归作者本人若汝棋茗所有 +// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按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.Log; +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Runtime.Serialization.Json; +using System.Text; + +namespace RRQMSocket.RPC.JsonRpc +{ + /// + /// WebApi解析器 + /// + public class JsonRpcParser : RPCParser, IService + { + /// + /// 构造函数 + /// + public JsonRpcParser() + { + this.tcpService = new RRQMTcpService(); + this.actionMap = new ActionMap(); + this.tcpService.CreatSocketCliect += this.OnCreatSocketCliect; + this.tcpService.OnReceived += this.OnReceived; + } + + /// + /// 在初次接收时 + /// + /// + /// + private void OnCreatSocketCliect(RRQMSocketClient socketClient, CreatOption creatOption) + { + if (creatOption.NewCreate) + { + socketClient.DataHandlingAdapter = new TerminatorDataHandlingAdapter(this.BufferLength, "\r\n"); + } + } + + private RRQMTcpService tcpService; + + /// + /// 函数键映射图 + /// + public ActionMap ActionMap { get { return this.actionMap; } } + + private ActionMap actionMap; + + /// + /// 获取当前服务通信器 + /// + public RRQMTcpService Service { get { return this.tcpService; } } + + /// + /// 获取绑定状态 + /// + public bool IsBind => this.tcpService.IsBind; + + /// + /// 获取或设置缓存大小 + /// + public int BufferLength { get { return this.tcpService.BufferLength; } set { this.tcpService.BufferLength = value; } } + + /// + /// 获取内存池实例 + /// + public BytePool BytePool => this.tcpService.BytePool; + + /// + /// 获取或设置日志记录器 + /// + public ILog Logger { get { return this.tcpService.Logger; } set { this.tcpService.Logger = value; } } + + /// + /// 绑定服务 + /// + /// 端口号 + /// 多线程数量 + /// + /// + /// + public void Bind(int port, int threadCount = 1) + { + this.tcpService.Bind(port, threadCount); + } + + /// + /// 绑定服务 + /// + /// ip和端口号,格式如“127.0.0.1:7789”。IP可输入Ipv6 + /// 多线程数量 + /// + /// + /// + public void Bind(IPHost iPHost, int threadCount) + { + this.tcpService.Bind(iPHost, threadCount); + } + + /// + /// 绑定服务 + /// + /// 寻址方案 + /// 绑定节点 + /// 多线程数量 + /// + /// + /// + public void Bind(AddressFamily addressFamily, EndPoint endPoint, int threadCount) + { + this.tcpService.Bind(addressFamily, endPoint, threadCount); + } + + private void OnReceived(RRQMSocketClient socketClient, ByteBlock byteBlock, object obj) + { + MethodInvoker methodInvoker = new MethodInvoker(); + methodInvoker.Flag = socketClient; + MethodInstance methodInstance = null; + try + { + RpcRequestContext context = this.BuildRequestContext(byteBlock, out methodInstance); + if (methodInstance == null) + { + methodInvoker.Status = InvokeStatus.UnFound; + } + else if (methodInstance.IsEnable) + { + methodInvoker.Parameters = context.@params; + } + else + { + methodInvoker.Status = InvokeStatus.UnEnable; + } + } + catch (Exception ex) + { + methodInvoker.Status = InvokeStatus.Exception; + methodInvoker.StatusMessage = ex.Message; + } + this.ExecuteMethod(methodInvoker, methodInstance); + } + + + /// + /// 结束调用 + /// + /// + /// + protected sealed override void EndInvokeMethod(MethodInvoker methodInvoker, MethodInstance methodInstance) + { + + } + + + /// + /// 初始化 + /// + /// + protected sealed override void InitializeServers(MethodInstance[] methodInstances) + { + foreach (var methodInstance in methodInstances) + { + foreach (var att in methodInstance.RPCAttributes) + { + if (att is JsonRpcAttribute attribute) + { + if (methodInstance.IsByRef) + { + throw new RRQMRPCException("JsonRpc服务中不允许有out及ref关键字"); + } + string actionKey = string.IsNullOrEmpty(attribute.MethodKey) ? methodInstance.Method.Name : attribute.MethodKey; + + try + { + this.actionMap.Add(actionKey, methodInstance); + } + catch + { + throw new RRQMRPCException($"函数键为{actionKey}的方法已注册。"); + } + + } + } + } + } + + /// + /// 构建请求内容 + /// + /// 数据 + /// 调用服务实例 + /// + protected virtual RpcRequestContext BuildRequestContext(ByteBlock byteBlock, out MethodInstance methodInstance) + { + byteBlock.Seek(0, SeekOrigin.Begin); + RpcRequestContext context = (RpcRequestContext)ReadObject(typeof(RpcRequestContext), byteBlock); + + if (this.actionMap.TryGet(context.method, out methodInstance)) + { + if (context.@params != null) + { + for (int i = 0; i < context.@params.Length; i++) + { + string s = context.@params[i].ToString(); + MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(s)); + memoryStream.Seek(0, SeekOrigin.Begin); + context.@params[i] = ReadObject(methodInstance.ParameterTypes[i], memoryStream); + } + } + } + else + { + methodInstance = null; + } + return context; + } + + private object ReadObject(Type type, Stream stream) + { + DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(RpcRequestContext)); + return deseralizer.ReadObject(stream); + } + + /// + /// 释放资源 + /// + public override void Dispose() + { + this.tcpService.Dispose(); + } + } +} \ No newline at end of file diff --git a/RRQMSocket.Json/RRQM.ico b/RRQMSocket.RPC.JsonRpc/RRQM.ico similarity index 100% rename from RRQMSocket.Json/RRQM.ico rename to RRQMSocket.RPC.JsonRpc/RRQM.ico diff --git a/RRQMSocket.Json/RRQM.png b/RRQMSocket.RPC.JsonRpc/RRQM.png similarity index 100% rename from RRQMSocket.Json/RRQM.png rename to RRQMSocket.RPC.JsonRpc/RRQM.png diff --git a/RRQMSocket.Json/RRQMSocket.JsonRpc.csproj b/RRQMSocket.RPC.JsonRpc/RRQMSocket.RPC.JsonRpc.csproj similarity index 98% rename from RRQMSocket.Json/RRQMSocket.JsonRpc.csproj rename to RRQMSocket.RPC.JsonRpc/RRQMSocket.RPC.JsonRpc.csproj index 99d775ba4..52cf6bba5 100644 --- a/RRQMSocket.Json/RRQMSocket.JsonRpc.csproj +++ b/RRQMSocket.RPC.JsonRpc/RRQMSocket.RPC.JsonRpc.csproj @@ -70,6 +70,6 @@ - + diff --git a/RRQMSocket.RPC.XmlRpc/Attribute/XmlRpcAttribute.cs b/RRQMSocket.RPC.XmlRpc/Attribute/XmlRpcAttribute.cs index 04fcb8849..e07bf7774 100644 --- a/RRQMSocket.RPC.XmlRpc/Attribute/XmlRpcAttribute.cs +++ b/RRQMSocket.RPC.XmlRpc/Attribute/XmlRpcAttribute.cs @@ -16,7 +16,7 @@ namespace RRQMSocket.RPC.XmlRpc /// /// 适用于XmlRpc的标记 /// - [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public sealed class XmlRpcAttribute : RPCMethodAttribute { /// diff --git a/RRQMSocket.sln b/RRQMSocket.sln index f5effedb4..570d04199 100644 --- a/RRQMSocket.sln +++ b/RRQMSocket.sln @@ -15,7 +15,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RRQMSocket.RPC.WebApi", "RR EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RRQMSocket.RPC.XmlRpc", "RRQMSocket.RPC.XmlRpc\RRQMSocket.RPC.XmlRpc.csproj", "{7A7EFF80-EBDD-4205-901F-B8F4C22307DF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RRQMSocket.JsonRpc", "RRQMSocket.Json\RRQMSocket.JsonRpc.csproj", "{9E5DDC4E-4C72-4AD0-B3FF-404391B8B2CF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RRQMSocket.RPC.JsonRpc", "RRQMSocket.RPC.JsonRpc\RRQMSocket.RPC.JsonRpc.csproj", "{0E36E1FE-49AB-4F69-86AB-710E2AD880D8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -47,10 +47,10 @@ Global {7A7EFF80-EBDD-4205-901F-B8F4C22307DF}.Debug|Any CPU.Build.0 = Debug|Any CPU {7A7EFF80-EBDD-4205-901F-B8F4C22307DF}.Release|Any CPU.ActiveCfg = Release|Any CPU {7A7EFF80-EBDD-4205-901F-B8F4C22307DF}.Release|Any CPU.Build.0 = Release|Any CPU - {9E5DDC4E-4C72-4AD0-B3FF-404391B8B2CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E5DDC4E-4C72-4AD0-B3FF-404391B8B2CF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E5DDC4E-4C72-4AD0-B3FF-404391B8B2CF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E5DDC4E-4C72-4AD0-B3FF-404391B8B2CF}.Release|Any CPU.Build.0 = Release|Any CPU + {0E36E1FE-49AB-4F69-86AB-710E2AD880D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E36E1FE-49AB-4F69-86AB-710E2AD880D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E36E1FE-49AB-4F69-86AB-710E2AD880D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E36E1FE-49AB-4F69-86AB-710E2AD880D8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE