我们来做一个头为6位报文总长度,并且长度不包含长度域自身的例子。比如这样的Socket报文000006123456
。
添加SuperSocket.Engine,直接使用Nuget搜索SuperSocket.Engine安装即可,依赖项为SuperSocket和log4net。
这里注意,SuperSocket 2.0以后没有SuperSocket.Engine了,直接使用SuperSocket即可,但是由于我这次是在.net framework 4.7的环境下使用,SuperSocket 2.0最低支持.net standard 2.1即只能支持.net core已经.net 5 6了,所以这里没法使用。
创建一个ReceiveFilter。
public class LengthReceiveFilter: FixedHeaderReceiveFilter<StringRequestInfo>
{
public LengthReceiveFilter() : base(6)
{
}
protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
{
return int.Parse(Encoding.Default.GetString(header, offset, length));
}
protected override StringRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
{
return new StringRequestInfo("", Encoding.UTF8.GetString(bodyBuffer, offset, length), null);
}
}
这里我们需要重写两个方法,以及调用一下父类的构造方法。
public LengthReceiveFilter() : base(6)
这里的6代表头长度为6位。
在protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
方法中,header即为截取到的6位报文头的byte数组,offset是偏移量,length是长度,返回值为报文的总长度。
由于我们报文格式中前六位为数字格式的报文长度,所以我们可以直接用int.Parse(Encoding.Default.GetString(header, offset, length))
来获取报文长度,如果长度包含长度本身,那要在-6,这里返回的是报文体的长度,如果返回的长度过长,则会不断的等待后续包。
protected override StringRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
是真正的解析方法,
把我们的报文转换成RequestInfo
。这里我们直接用StringRequestInfo
,就是把报文简单粗暴的直接转换成字符串。其中header就是我们的报文头的数据,如果这里还需要报文头就从header中拿,bodyBuffer就是我们的报文内容,offset是偏移量,length是长度。
如果我们在GetBodyLengthFromHeader
方法中返回的长度比报文体还要长,那么就一直不会走到ResolveRequestInfo
这个方法中。
新建一个
MyAppServer
继承AppServer
public class MyAppServer : AppServer
{
public MyAppServer() : base(new DefaultReceiveFilterFactory<LengthReceiveFilter,StringRequestInfo>())
{
}
}
这里我们直接用DefaultReceiveFilterFactory
这个内置的工厂来绑定我们的Filter
。
启动服务器
private void button1_Click(object sender, EventArgs e)
{
AppServer appServer = new MyAppServer();
appServer.NewSessionConnected += session =>
{
};
appServer.NewRequestReceived += (session, info) =>
{
MessageBox.Show(info.Body);
session.Send("hello");
session.Close();
};
if (!appServer.Setup(1234))
{
MessageBox.Show("服务器设置失败");
return;
}
if (!appServer.Start())
{
MessageBox.Show("服务器启动失败");
return;
}
}
我们可以直接new MyAppServer
来创建服务器。Setup
方法的参数是端口号,我们使用appServer.Setup(1234)
即把SocketServer监听的端口号设置为1234,appServer.Start()
正式开启服务器。
appServer.NewSessionConnected
是有新客户端连接上来的事件,这时候我们可以给客户端发送欢迎信息,或者执行一些其他操作。
appServer.NewRequestReceived
是接收到新消息的事件,我们在这里可以拿到RequestInfo
,从而获取到对应的信息。并且可以直接通过Send
方法来返回消息。
这里需要注意的是如果Send
直接使用字符串重载,那么会使用默认的编码格式,如果报文时UTF-8的,那么建议先用Encoding.UTF8.GetBytes
转成byte数组,然后用Send
的数组重载来发送内容。
关闭服务器
appServer.Stop();
即可关闭服务器。