什么是协议? 很多人会回答 "TCP" 或者 "UDP"。 但是构建一个网络应用程序, 仅仅知道是 TCP 还是 UDP 是远远不够的。 TCP 和 UDP 是传输层协议。仅仅定义了传输层协议是不能让网络的两端进行通信的。你需要定义你的应用层通信协议把你接收到的二进制数据转化成你程序能理解的请求。
在supersocket默认的协议是空格来分割请求的Key和参,定义以空格和换行符来进行结束标志
下面可以参考一下我设置的自定义命令协议
创建BuiltInPipelineFilter 类
代码:
using System;
using System.Buffers;
using System.Text;
//解析器
public class BuiltInPipelineFilter : TerminatorCustomTextPipelineFilter
{
public BuiltInPipelineFilter() : base((ReadOnlyMemory<byte>)new byte[10] { 32, 80, 101, 97, 99, 101, 84, 97, 108, 107 })//< PeaceTalk>
{
}
}
public class TerminatorCustomTextPipelineFilter : TerminatorPipelineFilter<TextPackageInfo>
{
public TerminatorCustomTextPipelineFilter(ReadOnlyMemory<byte> terminator) : base(terminator)
{
}
protected override TextPackageInfo DecodePackage(ref ReadOnlySequence<byte> buffer)
{
var text = GetStringFromReadOnlySequence(buffer);
return new TextPackageInfo
{
Text = text
};
}
public virtual string GetStringFromReadOnlySequence(ReadOnlySequence<byte> buffer)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Encoding encoding = Encoding.GetEncoding("GB2312");
var text = encoding.GetString(buffer);
Console.WriteLine($"接收到数据:{text}");
return text;
}
}
1.其中在BuiltInPipelineFilter 构造函数中定义
ReadOnlyMemory<byte>)new byte[10] { 32, 80, 101, 97, 99, 101, 84, 97, 108, 107 }
来进行设置命令终止协议 编码 32, 80, 101, 97, 99, 101, 84, 97, 108, 107 意思是结尾以空格加PeaceTalk 示例终止命令
2.在继承类TerminatorCustomTextPipelineFilter继承内置模板TerminatorPipelineFilter
使用的数据包类为TextPackageInfo
在TerminatorCustomTextPipelineFilter中需要把编码传递给模板进行解析,通俗一点的意思就是数据包过来了,以空格加PeaceTalk来过滤出消息
并在TerminatorCustomTextPipelineFilter中进行消息解码
注意:这里需要重写数据包解析方法,并我使用gb2312来进行解析,因为我使用的socket工具进行测试的,使用的是gb2312,所以有的时候如果你发送数据包中带中文,出现乱码,就是这个地方没有进行正确的编码解析
数据包分析
如果你要实现你自己的数据包分析类 只需要继承模板使用数据包类,在接收消息中进行配合使用就ok了 我定义的数据格式为 {头枚举}+{功能类型}+{主体} PeaceTalk
下面是我的代码示例
创建 SocketCodeAnalysis 类
//数据包分析
public class SocketCodeAnalysis : TextPackageInfo
{
#region 数据格式化 {头枚举}+{功能类型}+{主体} PeaceTalk
public _socketEnum Head { get; set; }
public SocketCodeBase Key { get; set; }
public string Body { get; set; }
public SocketCodeAnalysis(string text)
{
base.Text = text;
this.AnalysisPackage();
}
private void AnalysisPackage()
{
var val = base.Text;
var strList = val.Split("+");
if (strList.Length != 3) throw new Exception("Socket报文错误");
var str = string.Empty;
for (int i = 0; i < strList.Length; i++)
{
if (i == 0)
{
var head = AnalysisCode(strList[i]);
var judge = Enum.TryParse<_socketEnum>(head, out var headEnum);
if (judge) Head = headEnum;
}
if (i == 1)
{
var key = AnalysisCode(strList[i]);
Type type = Type.GetType("Super." + key);
if (type != null)
{
var obj = (SocketCodeBase)Activator.CreateInstance(type);
var check = CheckOut(obj);
if (!check) throw new Exception("报文验证失败");
}
}
if (i == 2)
{
var body = AnalysisCode(strList[i]);
//body = EncodingConvert(body);
var judge = body.Length > 0;
if (judge) Body = body;
}
}
}
private bool CheckOut(object obj)
{
switch (Head)
{
case _socketEnum.PrivateLaw:
if (obj is SocketCodeBase)
{
Key=(SocketPrivateLaw)obj;
return true;
}
break;
case _socketEnum.Broadcast:
if (obj is SocketCodeBase)
{
Key = (SocketBroadcast)obj;
return true;
}
break;
case _socketEnum.ServiceFunc:
if (obj is SocketCodeBase)
{
Key = (SocketServiceFunc)obj;
return true;
}
break;
default:
throw new Exception("Socket报文错误");
}
return false;
}
private string AnalysisCode(string value)
{
var star = value.IndexOf('{') + 1;
var len = value.IndexOf('}')-1;
var result = value.Substring(star, len);
return result;
}
#endregion
}
以上代码如果需要完整的可以看下一篇文章