C# 使用SuperSocket的FixedHeaderReceiveFilter進行通訊

【君莫笑】發表於2024-10-28
一、服務端
public
partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { MyServer appServer = new MyServer(); var se = new SuperSocket.SocketBase.Config.ServerConfig(); se.TextEncoding = "Unicode";// System.Text.Encoding. se.TextEncoding = "gbk";// System.Text.Encoding. se.Ip = "127.0.0.1"; se.Port = 2020; se.Mode = SocketMode.Tcp; if (!appServer.Setup(se)) //Setup with listening port { Console.WriteLine("Failed to setup!"); Console.ReadKey(); return; } Console.WriteLine(); //Try to start the appServer if (!appServer.Start()) { Console.WriteLine("Failed to start!"); Console.ReadKey(); return; } //appServer.NewSessionConnected += appServer_NewSessionConnected; //appServer.SessionClosed += appServer_SessionClosed; appServer.NewRequestReceived += appServer_NewRequestReceived; } static void appServer_NewRequestReceived(MySession session, BinaryRequestInfo requestInfo) { string key = requestInfo.Key; switch (key) { case "1": Console.WriteLine("Get message from " + session.RemoteEndPoint.ToString() + ":" + System.Text.Encoding.UTF8.GetString(requestInfo.Body)); break; case "2": Console.WriteLine("Get image"); break; default: Console.WriteLine("Get unknown message."); break; } } }
 public class MyServer : AppServer<MySession, BinaryRequestInfo>
    {
        public MyServer()
            : base(new DefaultReceiveFilterFactory<MyReceiveFilter, BinaryRequestInfo>()) //使用預設的接受過濾器工廠 (DefaultReceiveFilterFactory)
        {
        }
    }

    public class MySession : AppSession<MySession, BinaryRequestInfo>
    {
    }
public class MyReceiveFilter : FixedHeaderReceiveFilter<BinaryRequestInfo>
    {

        public MyReceiveFilter()
            : base(10)//訊息頭部長度
        { }
        /// <summary>
        ///
        /// </summary>
        /// <param name="header">*byte[] header * 快取的資料,這個並不是單純只包含協議頭的資料,有時候tcp協議長度為409600,很多</param>
        /// <param name="offset">頭部資料從 快取的資料 中開始的索引,一般為0.(tcp協議有可能從405504之類的一個很大資料開始)</param>
        /// <param name="length">這個length和base(10)中的引數相等</param>
        /// <returns></returns>
        protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
        {
            return GetBodyLengthFromHeader(header, offset, length, 6, 4);//6表示第幾個位元組開始表示長度.4:由於是int來表示長度,int佔用4個位元組
        }
        protected override BinaryRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
        {

            byte[] body = new byte[length];
            Array.Copy(bodyBuffer, offset, body, 0, length);

            Int16 type = BitConverter.ToInt16(header.Array, 4);

            BinaryRequestInfo r = new BinaryRequestInfo(type.ToString(), body);
            return r;

            //以下的程式碼,不解析body,全部返給上一層
            //byte[] h = header.ToArray();
            //byte[] full = new byte[h.Count()+length];
            //Array.Copy(h, full, h.Count());
            //Array.Copy(body, 0, full, h.Count(), body.Length );
            //BinaryRequestInfo r = new BinaryRequestInfo("",full);
            //return r;

        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="header">需要解析的資料</param>
        /// <param name="offset">頭部資料從header中開始的索引,一般為0,也可能不是0</param>
        /// <param name="length">這個length和base(10)中的引數相等</param>
        /// <param name="lenStartIndex">表示長度的位元組從第幾個開始</param>
        /// <param name="lenBytesCount">幾個位元組來表示長度:4個位元組=int,2個位元組=int16,1個位元組=byte</param>
        /// <returns></returns>
        private int GetBodyLengthFromHeader(byte[] header, int offset, int length, int lenStartIndex, int lenBytesCount)
        {
            var headerData = new byte[lenBytesCount];
            Array.Copy(header, offset + lenStartIndex, headerData, 0, lenBytesCount);//
            if (lenBytesCount == 1)
            {
                int i = headerData[0];
                return i;
            }
            else if (lenBytesCount == 2)
            {
                int i = BitConverter.ToInt16(headerData, 0);
                return i;
            }
            else //  if (lenBytesCount == 4)
            {
                int i = BitConverter.ToInt32(headerData, 0);
                return i;
            }
        }
    }
二、客戶端
 public class MyTcpClient
    {
        private System.Net.Sockets.TcpClient tcpClient;
        public MyTcpClient(string ip, int port)
        {

            tcpClient = new System.Net.Sockets.TcpClient(ip, port);
            byte[] recData = new byte[1024];
            Action a = new Action(() =>
            {
                while (true)
                {
                    tcpClient.Client.Receive(recData);
                    var msg = System.Text.Encoding.UTF8.GetString(recData);
                    Console.WriteLine(msg);
                }
            });
            a.BeginInvoke(null, null);

        }

        public void Send(string message)
        {
            var data = System.Text.Encoding.UTF8.GetBytes(message);
            tcpClient.Client.Send(data);
        }
        public void Send(byte[] message)
        {
            tcpClient.Client.Send(message);
        }
    }
public class SuperSocketMessage
    {
        public byte[] Start;//4個位元組
        public ushort Type;//2個位元組, 1表示文字訊息,2表示圖片訊息,其他表示未知,不能解析
        public int Len;//4個位元組
        public string Message;//文字資訊
        public byte[] Tail;//訊息結尾

        public SuperSocketMessage()
        {
            Start = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };
            Tail = new byte[] { 0x1F, 0x1F, 0x1F, 0x1F };
        }

        public byte[] ToBytes()
        {
            List<byte> list = new List<byte>();
            list.AddRange(Start);
            var t = BitConverter.GetBytes(Type);
            list.AddRange(t);

            var t3 = System.Text.Encoding.UTF8.GetBytes(Message);
            var t2 = BitConverter.GetBytes(t3.Length);//注意,這裡不是Message.Length,而是Message轉化成位元組陣列後的Lenght

            list.AddRange(t2);
            list.AddRange(t3);

            return list.ToArray();
        }
    }
        private void button1_Click(object sender, EventArgs e)
        {
            MyTcpClient c = new MyTcpClient("127.0.0.1", 2020);
            SuperSocketMessage msg = new SuperSocketMessage();
            msg.Type = 1;
            msg.Message = "aaa"; ;
            byte[] bytes = msg.ToBytes();
            string hexString = BitConverter.ToString(bytes).Replace("-", "");
            c.Send(msg.ToBytes());

        }
來源:https://blog.csdn.net/ba_wang_mao/article/details/118788365

相關文章