Dmtp基础功能
定义
命名空间:TouchSocket.Dmtp
程序集:TouchSocket.Dmtp.dll
一、连接
连接验证可以初步保证连接客户端的安全性。框架内部默认使用一个string
类型的Token
作为验证凭证。当然也允许服务器进行其他验证。具体如下:
1.1 Token验证
在服务器或客户端的配置上,设置VerifyToken
,即可实现字符串Token
验证。
var config = new TouchSocketConfig()
.SetDmtpOption(new DmtpOption()
{
VerifyToken = "Dmtp"
});
1.2 动态验证
使用插件,实现IDmtpHandshakingPlugin插件。然后可以自行判断一些信息,例如元数据等。
如果是特定协议的Dmtp
,还可以判断一些特定信息,例如,在TcpDmtp
中,可以判断IP
地址等。
客户端,在连接时,可以设置元数据。
var config = new TouchSocketConfig()
.SetDmtpOption(new DmtpOption()
{
Metadata=new Metadata().Add("a","a")
});
服务端使用插件验证连接信息。
internal class MyVerifyPlugin : PluginBase, IDmtpHandshakingPlugin
{
public async Task OnDmtpHandshaking(IDmtpActorObject client, DmtpVerifyEventArgs e)
{
if (e.Metadata["a"] != "a")
{
e.IsPermitOperation = false;//不允许连接
e.Message = "元数据不对";//同时返回消息
//表示该消息已在此处处理。
return;
}
if (client is ITcpDmtpSessionClient sessionClient)
{
//在特定协议的情况下,可以获取特定信息
var ip = sessionClient.IP;
}
if (e.Token == "Dmtp")
{
e.IsPermitOperation = true;//允许连接
}
await e.InvokeNext();
}
}
1.4 跨语言
为使Dmtp
支持跨语言,Dmtp
在设计之初就预留了跨语言连接的便利性。诚如Dmtp描述所示,其基础数据报文为Head+Flags+Length+Data
。而框架内部的Handshake
、Ping
、Pong
、Close
等指令均是采用Json
数据格式。但是即使如此,连接时的真正数据,还与其基础协议有关。具体如下:
以连接、操作TcpDmtpService
为例。其基础协议即为tcp
,则使用常规的tcp
客户端即可模拟链接。
using var tcpClient = new TcpClient();//创建一个普通的tcp客户端。
tcpClient.Received = (client, e) =>
{
//此处接收服务器返回的消息
var head = e.ByteBlock.ToArray(0, 2);
e.ByteBlock.Seek(2, SeekOrigin.Begin);
var flags = e.ByteBlock.ReadUInt16(EndianType.Big);
var length = e.ByteBlock.ReadInt32(EndianType.Big);
var json = e.ByteBlock.Span.ToString(Encoding.UTF8);
ConsoleLogger.Default.Info($"收到响应:flags={flags},length={length},json={json.Replace("\r\n", string.Empty).Replace(" ", string.Empty)}");
return Task.CompletedTask;
};
//开始链接服务器
await tcpClient.ConnectAsync("127.0.0.1:7789");
//以json的数据方式。
//其中Token、Metadata为连接的验证数据,分别为字符串、字符串字典类型。
//Id则表示指定的默认id,字符串类型。
//Sign为本次请求的序号,一般在连接时指定一个大于0的任意数字即可。
var json = @"{""Token"":""Dmtp"",""Metadata"":{""a"":""a""},""Id"":null,""Sign"":1}";
//将json转为utf-8编码。
var jsonBytes = Encoding.UTF8.GetBytes(json);
using (var byteBlock = new ByteBlock(1024*64))
{
//按照Head+Flags+Length+Data的格式。
byteBlock.Write(Encoding.ASCII.GetBytes("dm"));
byteBlock.Write(TouchSocketBitConverter.BigEndian.GetBytes((ushort)1));
byteBlock.Write(TouchSocketBitConverter.BigEndian.GetBytes((int)jsonBytes.Length));
byteBlock.Write(jsonBytes);
await tcpClient.SendAsync(byteBlock.Memory);
}
await Task.Delay(2000);
接收输出:
收 到的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}