SuperSocket 1.6 建立一個簡易的報文長度在頭部的Socket伺服器

jvx發表於2022-07-06

我們來做一個頭為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();

即可關閉伺服器。

相關文章