模板解析“大数据固定包头”数据适配器
定义
命名空间:TouchSocket.Core
程序集:TouchSocket.Core.dll
一、说明
大数据固定包头,是对固定的包头模板的补充,一般来是,固定包头适配器,不能工作于超过2G的数据,但是在少数情况下,会有大量的数据传输需求。所以这部分的业务,可以用大数据固定包头实现。
二、特点
- 可以随意定制数据协议。
- 可以与任意语言、框架对接数据。
- 可以接收理论无限大的数据。
三、创建适配器
客户端与服务器均适用。下列以服务器为例。
步骤
- 声明新建类,实现
IBigFixedHeaderRequestInfo
接口,此对象即为存储数据的实体类,可在此类中声明一些属性,以备使用。 - 声明新建类,继承
CustomBigFixedHeaderDataHandlingAdapter
,并且以步骤1声明的类作为泛型。并实现对应抽象方法。 TouchSocketConfig
配置中设置。- 通过
Received
(事件、方法、插件)中的RequestInfo
对象,强转为步骤1声明的类型,然后读取其属性值,以备使用。
【MyBigFixedHeaderRequestInfo】
首先,新建MyBigFixedHeaderRequestInfo
类,然后实现IBigFixedHeaderRequestInfo
用户自定义固定包头接口。
然后在OnParsingHeader
函数执行结束时,对实现的BodyLength
属性作出赋值,以此来决定,后续还应该接收多少数据作为Body
。
class MyBigFixedHeaderRequestInfo : IBigFixedHeaderRequestInfo
{
/// <summary>
/// 自定义属性,标识数据类型
/// </summary>
public byte DataType { get; set; }
/// <summary>
/// 自定义属性,标识指令类型
/// </summary>
public byte OrderType { get; set; }
/// <summary>
/// 自定义属性,标识实际数据
/// </summary>
public byte[] Body { get; set; }
private long m_bodyLength;
List<byte> m_bytes=new List<byte>();
#region 接口成员
long IBigFixedHeaderRequestInfo.BodyLength => m_bodyLength;
void IBigFixedHeaderRequestInfo.OnAppendBody(ReadOnlySpan<byte> buffer)
{
//每次追加数据
m_bytes.AddRange(buffer.ToArray());
}
bool IBigFixedHeaderRequestInfo.OnFinished()
{
if (m_bytes.Count == this.m_bodyLength)
{
this.Body = m_bytes.ToArray();
return true;
}
return false;
}
bool IBigFixedHeaderRequestInfo.OnParsingHeader(ReadOnlySpan<byte> header)
{
//在该示例中,第一个字节表示后续的所有数据长度,但是header设置的是3,所以后续还应当接收length-2个长度。
this.m_bodyLength = header[0] - 2;
this.DataType = header[1];
this.OrderType = header[2];
return true;
}
#endregion
}
新建MyCustomBigFixedHeaderDataHandlingAdapter
继承CustomBigFixedHeaderDataHandlingAdapter
,然后对HeaderLength
作出赋值,以此表明固定包头的长度是多少。
class MyCustomBigFixedHeaderDataHandlingAdapter : CustomBigFixedHeaderDataHandlingAdapter<MyBigFixedHeaderRequestInfo>
{
public override int HeaderLength => 3;
protected override MyBigFixedHeaderRequestInfo GetInstance()
{
return new MyBigFixedHeaderRequestInfo();
}
}
四、使用
private static async Task<TcpClient> CreateClient()
{
var client = new TcpClient();
//载入配置
await client.SetupAsync(new TouchSocketConfig()
.SetRemoteIPHost("127.0.0.1:7789")
.SetTcpDataHandlingAdapter(() => new MyCustomBigFixedHeaderDataHandlingAdapter())
.ConfigureContainer(a =>
{
a.AddConsoleLogger();//添加一个日志注入
}));
await client.ConnectAsync();//调用连接,当连接不成功时,会抛出异常。
client.Logger.Info("客户端成功连接");
return client;
}
private static async Task<TcpService> CreateService()
{
var service = new TcpService();
service.Received = (client, e) =>
{
//从客户端收到信息
if (e.RequestInfo is MyBigFixedHeaderRequestInfo myRequest)
{
client.Logger.Info($"已从{client.Id}接收到:DataType={myRequest.DataType},OrderType={myRequest.OrderType},消息={Encoding.UTF8.GetString(myRequest.Body)}");
}
return Task.CompletedTask;
};
await service.SetupAsync(new TouchSocketConfig()//载入配置
.SetListenIPHosts("tcp://127.0.0.1:7789", 7790)//同时监听两个地址
.SetTcpDataHandlingAdapter(() => new MyCustomBigFixedHeaderDataHandlingAdapter())
.ConfigureContainer(a =>
{
a.AddConsoleLogger();//添加一个控制台日志注入(注意:在maui中控制台日志不可用)
})
.ConfigurePlugins(a =>
{
//a.Add();//此处可以添加插件
}));
await service.StartAsync();//启动
service.Logger.Info("服务器已启动");
return service;
}
提示
上述创建的适配器客户端与服务器均适用。