跳到主要内容
版本:2.1

模板解析“大数据固定包头”数据适配器

定义

命名空间:TouchSocket.Core
程序集:TouchSocket.Core.dll

一、说明

大数据固定包头,是对固定的包头模板的补充,一般来是,固定包头适配器,不能工作于超过2G的数据,但是在少数情况下,会有大量的数据传输需求。所以这部分的业务,可以用大数据固定包头实现。

二、特点

  1. 可以随意定制数据协议。
  2. 可以与任意语言、框架对接数据。
  3. 可以接收理论无限大的数据。

三、创建适配器

客户端与服务器均适用。下列以服务器为例。

步骤

  1. 声明新建类,实现IBigFixedHeaderRequestInfo接口,此对象即为存储数据的实体类,可在此类中声明一些属性,以备使用。
  2. 声明新建类,继承CustomBigFixedHeaderDataHandlingAdapter,并且以步骤1声明的类作为泛型。并实现对应抽象方法。
  3. TouchSocketConfig配置中设置。
  4. 通过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;
}
提示

上述创建的适配器客户端与服务器均适用。