最近正在完善一套面向远程方法调用的中间件,中间件设计初衷主要用于工控领域的分布式控制,因为中间件在前期已做了部分,但在框架化的设计上有问题,因此重新对底层协议进行修订。
修订此协议的目的是,配合Trace.RMI.Client.dll和Trace.RMI.Server.dll,两个调用组件的底层通信协议使用的,此协议中,如果需要客户端注册服务器端的回调应用,则必须在客户端启用长连接通信协议。其中的Trace.RMI.Server.dll提供了Windows服务或IIS服务的全局调用入口点,Windows服务下,配置了对应的TCP服务监听处理服务,IIS服务下配置了对应的Http监听服务。Trace.RMI.Client.dll调用时,需要与服务端启用的监听服务相匹配。
服务器端,每一个发起请求的会话连接,都会生成一个连接会话请求的上下文信息,其中包含了,发起请求的客户端对象ID,连接会话ID,注册的订阅回调信息ID列表,其中这些信息在每一次会话连接建立后,都会由系统在底层自动进行一次初始化,如果由于网络原因等,造成连接会话断开,则在自动建立网络连接时,会自动进行信息初始化处理。
下面是完整的协议部分,在后续会把中间的实现和调用过程的Demo开放出来。
1 通信协议包格式
用于对客户端和服务器端通信时,数据传输过程中的数据包的封装处理,只负责具体的数据
包传输,此为整个封包的最外层包装。
起始标记位 | 包体长度 | 加密标记 | 数据包内容 |
4Byte | Int32 | 1Byte | 字节流 |
用于标记数据包的开始, 0x02,0x03,0xFF,0xFF | 用于标记数据包的长度,LittleEndian | 0x00,不加密 0x01,加密 | 所有数据的内容,需要下面的“数据包内容协议格式定义”进一步处理 |
|
1.1 数据包内容协议格式定义:
包唯一ID | 包标记 | 数据块内容 | 数据包校验位 |
GUI(16Byte) | 1Byte | 字节流 | 1Byte |
当前传输数据包的唯一ID | 0x00,表示整包传输, 0x01,表示分包传输 0x02,表示整包传输确认 0x03,表示分包传输确认 | 需要下面进一步处理 | 校验和,对数据包内容中的所有数据,进行校验和 |
|
1.1.1 整包传输数据块协议
版本号 | 命令状态 | 执行体 |
Int32 | Byte | 字节流 |
用于标记处理数据的版本 | 0x00,请求命令 0x01,应答命令 | 需要到“执行体协议”进一步处理 |
|
1.1.2 整包传输数据块确认
发送包唯一ID |
GUID(16Byte) |
用于确认发送包的唯一ID |
用于整包传输数据时,应答方对发送方的确认动作 |
1.1.3 分包传输数据块协议
1.1.1.1 分包传输协议
原始包唯一ID | 原始包分块数量 | 当前包序列 | 原始包中起始字节位置 | 原始包中结束字节位置 | 块内容 |
GUID(16Byte) | Int32 | Int32 | Int32 | Int32 | 字节流 |
发起请求的最原始数据包字节流 | 原始数据包可拆分成多少个小的数据分包 | 当前小包,处于原始数据包分包中的位置 | 当前分包中的起始数据在原始数据包中的位置 | 当前分包中的结束数据在原始数据包中的位置 | 需要“拆分、合并整体数据块”进一步处理,调用时进行数据包的合并 |
|
1.1.1.2 分包传输协议,拆分、合并整体数据块
版本号 | 命令状态 | 执行体 |
Int32 | Byte | 字节流 |
用于标记处理数据的版本 | 0x00,请求命令 0x01,应答命令 | 需要到“执行体协议”进一步处理 |
|
1.1.4 分包传输数据块确认
发送包唯一ID | 原始整包唯一ID |
GUID(16Byte) | GUID(16Byte) |
用于确认发送包的唯一ID | 用于确认原始整包的唯一ID |
用于分包传输数据时,每一个小的分包,应答方对发送方的确认动作
|
2 客户端版本1,执行体协议
启用的序列化协议 | 请求方式 | 请求对象ID | 调用过程ID | 服务器端映射键字节流长度 | 服务器端映射键字节流 | 具体的调用请求 |
1Byte | 1Byte | GUID(16Byte) | GUID(16Byte) | Int32 | 字节流 | 字节流 |
0x00,Json序列化, 0x01,ProtoBuf序列化 | 0x01,注册订阅 0x02,同步调用请求 0x03,异步调用请求 | 用于标记客户端发起请求的对象 | 用于标记客户端发起请求的调用函数 | 用于标记服务器端映射键字节流长度 | 具体的字符内容,UTF8编码后的字节流 |
|
|
2.1 客户端注册订阅服务器端请求
注册订阅状态 | 订阅方法描述字节流长度 | 订阅方法描述字节流 | 请求参数数量 | 参数集合序列化处理 |
1Byte | Int32 | 字节流 | Int32 |
|
0x00,注册订阅, 0x01,取消注册订阅 | 用于标记订阅方法描述字节流长度 | 用于描述调用方法对应的字符串, UTF8编码后的字节流 | 用于描述调用方法的参数数量 | 需要到“注册订阅参数集合序列化处理”进一步处理,循环调用 |
|
2.1.1.1 注册订阅参数集合序列化处理
参数类型全名字节流长度 | 参数类型全名字节流 |
Int32 | 字节流 |
用于标记参数类型全名字节流长度 | 用于描述参数类型全名对应的字符串,UTF8编码后的字节流 |
|
2.2 函数同步调用请求
请求方法描述字节流长度 | 请求方法描述字节流 | 请求参数数量 | 参数集合序列化处理 | 返回类型全名字节流长度 | 返回类型全名字节流 |
Int32 | 字节流 | Int32 |
| Int32 | 字节流 |
用于标记请求方法描述字节流长度 | 用于描述调用方法对应的字符串, UTF8编码后的字节流 | 用于描述调用方法的参数数量 | 需要到“参数集合序列化处理”进一步处理 | 用于标记返回类型全名字节流长度 | 用于描述返回类型的全名字符串,UTF8编码 |
|
2.2.1.1 参数集合序列化处理
参数类型全名字节流长度 | 参数类型全名字节流 | 参数序列化内容字节流长度 | 参数序列化内容字节流 |
Int32 | 字节流 | Int32 | 字节流 |
用于标记参数类型全名字节流长度 | 用于描述参数类型全名对应的字符串,UTF8编码后的字节流 | 用于标记参数序列化内容字节流长度 | 将参数内容进行序列化后,并经UTF8编码后的字节流 |
|
2.3 函数异步调用请求
请求方法长度 | 请求方法描述 | 请求方法参数数量 | 请求参数集合序列化处理 | 异步回调方法名字节流长度 | 异步回调方法描述 | 回调方法参数数量 | 回调参数集合序列化处理 |
Int32 | 字节流 | Int32 | 字节流 | Int32 | 字节流 | Int32 | 字节流 |
用于标记调用方法对应的字符串长度 | 用于描述调用方法对应的字符串, UTF8编码后的字节流 | 用于描述请求方法的参数数量 | 需要到“请求参数集合序列化处理”进一步处理,循环调用 | 用于标记异步回调方法签名转码后的字节流长度 | 用于描述返回类型的全名字符串,UTF8编码 | 用于描述回调方法的参数数量 | 需要到“回调参数集合序列化处理”进一步处理,循环调用 |
|
2.3.1.1 请求参数集合序列化处理
参数类型全名字节流长度 | 参数类型全名字节流 | 参数序列化内容字节流长度 | 参数序列化内容字节流 |
Int32 | 字节流 | Int32 | 字节流 |
用于标记参数类型全名字节流长度 | 用于描述参数类型全名对应的字符串,UTF8编码后的字节流 | 用于标记参数序列化内容字节流长度 | 将参数内容进行序列化后,并经UTF8编码后的字节流 |
|
2.3.1.2 回调参数集合序列化处理
参数类型全名字节流长度 | 参数类型全名字节流 |
Int32 | 字节流 |
用于标记参数类型全名字节流长度 | 用于描述参数类型全名对应的字符串,UTF8编码后的字节流 |
|
3 服务端版本1,执行体协议
3.1 函数反馈应答
启用的序列化协议 | 客户端请求对象ID | 客户端调用过程ID | 应答方式 | 具体的应答处理 |
1Byte | GUID(16Byte) | GUID(16Byte) | 1Byte | 字节流 |
0x00,Json序列化, 0x01,ProtoBuf序列化 | 用于标记客户端发起请求的对象 | 用于标记客户端发起请求的调用函数 | 用于标记服务器端的应答方式, 0x01, 同步请求应答 0x02,订阅回调 0x03,异步请求应答
|
|
|
3.1.1 客户端同步请求应答
应答状态 | 返回数据 |
1Byte | 字节流 |
用于标记应答的信息流状态 0x00 空的返回 0x01 存在数据 0x02 异常信息 |
|
3.1.1.1 空的返回
直接返回协议包部分,无具体的反馈数据流。
3.1.1.2 存在数据
返回内容字节流长度 | 返回序列化内容 |
Int32 | 字节流 |
用于标记返回内容长度 | 将返回内容进行序列化后,并经UTF8编码后的字节流 |
|
3.1.1.3 异常信息
返回异常字节流长度 | 返回异常内容 |
Int32 | 字节流 |
用于标记返回异常字节流长度 | 将返回异常进行序列化后,并经UTF8编码后的字节流 |
|
3.1.2 客户端订阅回调应答
应答状态 | 返回参数数量 | 返回数据 |
1Byte | Int32 | 字节流 |
用于标记应答的信息流状态 0x01 存在数据 0x02 异常信息 | 用于标记回调函数返回时的参数数量 | 回调函数可能有多个输出参数,需要循环调用 |
3.1.2.1 返回数据序列化处理
返回类型全名字节流长度 | 返回类型全名字节流 | 返回序列化内容字节流长度 | 返回序列化内容字节流 |
Int32 | 字节流 | Int32 | 字节流 |
用于标记返回类型全名字节流长度 | 用于描述返回类型全名对应的字符串,UTF8编码后的字节流 | 用于标记返回序列化内容字节流长度 | 将返回内容进行序列化后,并经UTF8编码后的字节流 |
|
3.1.2.2 异常信息
返回异常字节流长度 | 返回异常内容 |
Int32 | 字节流 |
用于标记返回异常字节流长度 | 将返回异常进行序列化后,并经UTF8编码后的字节流 |
|
3.1.3 客户端异步请求应答
应答状态 | 返回数据 |
1Byte | 字节流 |
用于标记应答的信息流状态 0x00 空的返回 0x01 存在数据 0x02 异常信息 |
|
3.1.3.1 空的返回
直接返回协议包部分,无具体的反馈数据流。
3.1.3.2 存在数据
返回类型全名字节流长度 | 返回类型全名字节流 | 返回序列化内容字节流长度 | 返回序列化内容字节流 |
Int32 | 字节流 | Int32 | 字节流 |
用于标记返回类型全名字节流长度 | 用于描述返回类型全名对应的字符串,UTF8编码后的字节流 | 用于标记返回序列化内容字节流长度 | 将返回内容进行序列化后,并经UTF8编码后的字节流 |
|
3.1.3.3 异常信息
返回异常字节流长度 | 返回异常内容 |
Int32 | 字节流 |
用于标记返回异常字节流长度 | 将返回异常进行序列化后,并经UTF8编码后的字节流 |
|