我們來做一個頭為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();
即可關閉伺服器。