跳到主要内容
版本:4.0-rc

Dmtp基础功能

定义

命名空间:
TouchSocket.Dmtp
安装:
dotnet add package TouchSocket.Dmtp

一、连接

连接验证可以初步保证连接客户端的安全性。框架内部默认使用一个string类型的Token作为验证凭证。当然也允许服务器进行其他验证。具体如下:

1.1 Token验证

在服务器或客户端的配置上,设置VerifyToken,即可实现字符串Token验证。

🔄 正在加载代码...

1.2 动态验证

使用插件,实现IDmtpConnectingPlugin插件。然后可以自行判断一些信息,例如元数据等。

如果是特定协议的Dmtp,还可以判断一些特定信息,例如,在TcpDmtp中,可以判断IP地址等。

客户端,在连接时,可以通过Metadata设置元数据。

服务端使用插件验证连接信息。

🔄 正在加载代码...

1.4 跨语言

为使Dmtp支持跨语言,Dmtp在设计之初就预留了跨语言连接的便利性。诚如Dmtp描述所示,其基础数据报文为Head+Flags+Length+Data。而框架内部的HandshakePingPongClose等指令均是采用Json数据格式。但是即使如此,连接时的真正数据,还与其基础协议有关。具体如下:

以连接、操作TcpDmtpService为例。其基础协议即为tcp,则使用常规的tcp客户端即可模拟链接。

🔄 正在加载代码...

接收输出:

收到的Json字符串,会返回服务器最终修改的TokenMetadata。同时还包括分配或指定的IdSign会与请求时一致,表示这是同一组请求。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发送数据

ChannelDmtpActor的一个传输通道。一般来说,DmtpActor是一个逻辑连接(例如:一个TcpUdpNamedPipe等)。而Channel则是更加细分DmtpActor的一个传输通道。

换言之,一个DmtpActor可以有多个Channel。多个Channel可以同时进行传输。并且数据互不干扰。

4.1 特点

  1. 每个Channel都有独立的Id,所以多个Channel可以同时工作。
  2. 每个Channel在被创建后,都支持双向读写。
  3. 每个Channel都支持自定义限速和读写超时设定。

4.2 使用步骤

  1. 由一方DmtpActor创建一个Channel,并记住Id。
  2. 另一方DmtpActor使用这个Id订阅Channel。默认情况下,Channel在被创建时,接收端会触发IDmtpCreatedChannelPlugin插件。此时可以直接订阅。
  3. 发送方使用Channel发送(WriteAsync)数据
  4. 接收方通过订阅的Channel,接收(Read)数据

下列以TcpDmtpClient发送、TcpDmtpService接收为例:

【TcpDmtpClient创建Channel】

🔄 正在加载代码...

【TcpDmtpService】

🔄 正在加载代码...

4.3 终止语句

Channel的终止语句总共有4个:

  • Complete:完成,表示写入结束,接收端会收到完成的状态。
  • Cancel:取消,表示写入被取消,接收端会收到取消的状态。
  • HoldOn:等待继续,表示写入被中断,但是可以恢复传输,接收端会跳出接收,但是可以重新进入接收。
  • Dispose:释放,表示写入被释放,接收端会收到释放的状态。

其中CompleteCancelDispose均为一次性终止语句,即调用以后,Channel将不可再被使用。如果想再使用Channel,则必须重新创建,重新订阅。

HoldOn为可恢复的终止语句,调用以后,Channel会进入等待状态,接收端会跳出接收,但是可以重新进入接收。这在多段数据传输传输时是有用的。

4.4 注意事项

  1. Channel的传输是有序的。
  2. Channel支持所有的Dmtp组件,但要求是该组件必须基于可靠协议,例如:UdpDmtp则不支持。
  3. Channel拥有自己的拥塞控制,当发生拥塞的时候,不会阻塞底层协议。但是应该也要避免发生拥塞。
  4. Channel在使用完成后,必须显示释放,所以建议使用using关键字。

五、使用心跳、断线重连

Dmtp组件自带了Ping方法。这个方法强制要求被Ping的一方无条件响应的。

所以,如果Ping返回true,则说明对方必在线

但是如果返回false时,并不一定代表对方不在线

因为有可能是Ping超时,或者当前传输链路正在忙。

总之,使用者可以在业务中调用这个方法,来检测通讯是否通畅。

提示

Ping可以由客户端或服务器任意一端发起,然后要求对方回应。但是一般我们建议由客户端发起。由服务器响应即可。如果有特殊要求,则自行解决即可。

不过,为了方便使用,建议配合断线重连插件来实现心跳。

🔄 正在加载代码...

七、示例代码