Dmtp基础功能
定义
一、连接
连接验证可以初步保证连接客户端的安全性。框架内部默认使用一个string类型的Token作为验证凭证。当然也允许服务器进行其他验证。具体如下:
1.1 Token验证
在服务器或客户端的配置上,设置VerifyToken,即可实现字符串Token验证。
1.2 动态验证
使用插件,实现IDmtpConnectingPlugin插件。然后可以自行判断一些信息,例如元数据等。
如果是特定协议的Dmtp,还可以判断一些特定信息,例如,在TcpDmtp中,可以判断IP地址等。
客户端,在连接时,可以通过Metadata设置元数据。
服务端使用插件验证连接信息。
1.4 跨语言
为使Dmtp支持跨语言,Dmtp在设计之初就预留了跨语言连接的便利性。诚如Dmtp描述所示,其基础数据报文为Head+Flags+Length+Data。而框架内部的Handshake、Ping、Pong、Close等指令均是采用Json数据格式。但是即使如此,连接时的真正数据,还与其基础协议有关。具体如下:
以连接、操作TcpDmtpService为例。其基础协议即为tcp,则使用常规的tcp客户端即可模拟链接。
接收输出:
收到的Json字符串,会返回服务器最终修改的Token、Metadata。同时还包括分配或指定的Id。Sign会与请求时一致,表示这是同一组请求。Status等于1即为连接成功。其他值则可能在Message表明连接失败的原因。
收到响应:flags=2,length=124,json={"Token":"Dmtp","Metadata":{"a":"a"},"Id":"1","Message":null,"Sign":1,"Status":1}
其他Json请求,包括:
【请求连接】
- Token:连接令牌,字符串类型。
- Metadata:连接元数据,字典类型。
- Id:初始连接Id,字符串类型。
- Sign:请求序号,整数类型,应当每次请求递增。
- Status(仅返回时携带):连接状态,整数类型,为1时成功,其他状态可以获取Message。
- Message(仅返回时携带):连接消息。
{"Token":"Dmtp","Metadata":{"a":"a"},"Id":null,"Sign":1}
【Ping】
- Sign:请求序号,整数类型,应当每次请求递增。
- Status(仅返回时携带):连接状态,整数类型,为1时成功,其他状态可以获取Message。
- Message(仅返回时携带):连接消息。
- Route:是否路由,布尔类型,当TargetId不为空时应设为True。
- SourceId:源Id,字符串类型,当需要Ping其他客户端时,应该将该值设为自身Id,以保证返回的信息能够顺利路由回来。
- TargetId:目标Id,字符串类型,当需要Ping其他客户端时,应该将该值设为目标Id,以保证信息能够顺利送达。
{"Sign":0,"Status":0,"Message":null,"Route":false,"SourceId":null,"TargetId":null}
【Close】
Close报文直接采用utf8编码的字符串。
"close"
DMTP基础功能是比较容易跨语言的,但这并不意味着DMTP所有的功能都支持。其扩展功能,则需要实际的跨平台设计。不过依靠简单的Head+Flags+Length+Data的格式,也能自己实现很多的功能。
二、Id同步
在Dmtp中,存在于服务器的辅助客户端(SessionClient),与远程客户端(Client)是一一对应关系,其Id也完全一致。
所以在任意一方修改Id(调用ResetId),都会同时修改远程Id。所以合理使用该操作,可以完成复用Id(重置Id)的需求。
三、发送数据
Dmtp提供协议发送数据,又叫协议扩展功能,就是对现有的Dmtp进行自定义的扩展协议。
使用起来是非常简单的,每个DmtpActor,都实现了Send方法接口。
第一个参数为ushort类型,使用者可以约定任意大于20数值。
Flags不要使用小于20的,因为框架内部在使用。并且小于100的也最好不要使用,因为可能其他组件(例如:DmtpRpc等)也在使用。
在接收方订阅IDmtpReceivedPlugin,已经包含了协议参数,所以直接自行筛选即可。
四、使用Channel发送数据
Channel是DmtpActor的一个传输通道。一般来说,DmtpActor是一个逻辑连接(例如:一个Tcp、Udp、NamedPipe等)。而Channel则是更加细分DmtpActor的一个传输通道。
换言之,一个DmtpActor可以有多个Channel。多个Channel可以同时进行传输。并且数据互不干扰。
4.1 特点
- 每个
Channel都有独立的Id,所以多个Channel可以同时工作。 - 每个
Channel在被创建后,都支持双向读写。 - 每个
Channel都支持自定义限速和读写超时设定。
4.2 使用步骤
- 由一方
DmtpActor创建一个Channel,并记住Id。 - 另一方
DmtpActor使用这个Id订阅Channel。默认情况下,Channel在被创建时,接收端会触发IDmtpCreatedChannelPlugin插件。此时可以直接订阅。 - 发送方使用
Channel发送(WriteAsync)数据 - 接收方通过订阅的
Channel,接收(Read)数据
下列以TcpDmtpClient发送、TcpDmtpService接收为例:
【TcpDmtpClient创建Channel】
【TcpDmtpService】
4.3 终止语句
Channel的终止语句总共有4个:
- Complete:完成,表示写入结束,接收端会收到完成的状态。
- Cancel:取消,表示写入被取消,接收端会收到取消的状态。
- HoldOn:等待继续,表示写入被中断,但是可以恢复传输,接收端会跳出接收,但是可以重新进入接收。
- Dispose:释放,表示写入被释放,接收端会收到释放的状态。
其中Complete、Cancel、Dispose均为一次性终止语句,即调用以后,Channel将不可再被使用。如果想再使用Channel,则必须重新创建,重新订阅。
HoldOn为可恢复的终止语句,调用以后,Channel会进入等待状态,接收端会跳出接收,但是可以重新进入接收。这在多段数据传输传输时是有用的。
4.4 注意事项
Channel的传输是有序的。Channel支持所有的Dmtp组件,但要求是该组件必须基于可靠协议,例如:UdpDmtp则不支持。Channel拥有自己的拥塞控制,当发生拥塞的时候,不会阻塞底层协议。但是应该也要避免发生拥塞。Channel在使用完成后,必须显示释放,所以建议使用using关键字。
五、使用心跳、断线重连
Dmtp组件自带了Ping方法。这个方法强制要求被Ping的一方无条件响应的。
所以,如果Ping返回true,则说明对方必在线。
但是如果返回false时,并不一定代表对方不在线。
因为有可能是Ping超时,或者当前传输链路正在忙。
总之,使用者可以在业务中调用这个方法,来检测通讯是否通畅。
Ping可以由客户端或服务器任意一端发起,然后要求对方回应。但是一般我们建议由客户端发起。由服务器响应即可。如果有特殊要求,则自行解决即可。
不过,为了方便使用,建议配合断线重连插件来实现心跳。