1

SuperSocket 1.6 创建一个简易的报文长度在头部的Socket服务器 - jvx

 1 year ago
source link: https://www.cnblogs.com/j4587698/p/16451262.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

SuperSocket 1.6 创建一个简易的报文长度在头部的Socket服务器

我们来做一个头为6位报文总长度,并且长度不包含长度域自身的例子。比如这样的Socket报文000006123456

  1. 添加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了,所以这里没法使用。

  2. 创建一个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这个方法中。

  1. 新建一个MyAppServer继承AppServer

public class MyAppServer : AppServer
    {
        public MyAppServer() : base(new DefaultReceiveFilterFactory<LengthReceiveFilter,StringRequestInfo>())
        {
            
        }
    }

这里我们直接用DefaultReceiveFilterFactory这个内置的工厂来绑定我们的Filter

  1. 启动服务器

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的数组重载来发送内容。

  1. 关闭服务器

appServer.Stop();

即可关闭服务器。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK