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