VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > C#教程 >
  • SuperSocket 简单示例

这是一个SuperSocket 简单示例,包括服务端和客户端。

一、首先使用NuGet安装SuperSocket和SuperSocket.Engine

二、实现IRequestInfo(数据包):

数据包格式:

包头4个字节,前2个字节是请求命令,后2个字节是正文长度

复制代码
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SuperSocketServer
{
    public class MyRequestInfo : IRequestInfo
    {
        public MyRequestInfo(byte[] header, byte[] bodyBuffer)
        {
            Key = ASCIIEncoding.ASCII.GetString(new byte[] { header[0], header[1] });
            Data = bodyBuffer;
        }

        public string Key { get; set; }

        public byte[] Data { get; set; }

        public string Body
        {
            get
            {
                return Encoding.UTF8.GetString(Data);
            }
        }
    }
}
复制代码

三、实现FixedHeaderReceiveFilter(数据包解析):

复制代码
using SuperSocket.Facility.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SuperSocketServer
{
    public class MyReceiveFilter : FixedHeaderReceiveFilter<MyRequestInfo>
    {
        public MyReceiveFilter() : base(4)
        {

        }

        protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
        {
            return BitConverter.ToInt16(new byte[] { header[offset + 2], header[offset + 3] }, 0);
        }

        protected override MyRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
        {
            byte[] body = bodyBuffer.Skip(offset).Take(length).ToArray();
            return new MyRequestInfo(header.Array, body);
        }
    }
}
复制代码

四、实现AppSession:

复制代码
using SuperSocket.SocketBase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SuperSocketServer
{
    public class MySession : AppSession<MySession, MyRequestInfo>
    {
        public MySession()
        {

        }

        protected override void OnSessionStarted()
        {

        }

        protected override void OnInit()
        {
            base.OnInit();
        }

        protected override void HandleUnknownRequest(MyRequestInfo requestInfo)
        {

        }

        protected override void HandleException(Exception e)
        {

        }

        protected override void OnSessionClosed(CloseReason reason)
        {
            base.OnSessionClosed(reason);
        }
    }
}
复制代码

五、实现AppServer:

复制代码
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Utils;

namespace SuperSocketServer
{
    public class MyServer : AppServer<MySession, MyRequestInfo>
    {
        public MyServer() : base(new DefaultReceiveFilterFactory<MyReceiveFilter, MyRequestInfo>())
        {
            this.NewSessionConnected += MyServer_NewSessionConnected;
            this.SessionClosed += MyServer_SessionClosed;
        }

        protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
        {
            return base.Setup(rootConfig, config);
        }

        protected override void OnStarted()
        {
            base.OnStarted();
        }

        protected override void OnStopped()
        {
            base.OnStopped();
        }

        void MyServer_NewSessionConnected(MySession session)
        {
            LogHelper.Log("新客户端连接,SessionID=" + session.SessionID.Substring(session.SessionID.Length - 6).ToUpper());
        }

        void MyServer_SessionClosed(MySession session, CloseReason value)
        {
            LogHelper.Log("客户端失去连接,SessionID=" + session.SessionID.Substring(session.SessionID.Length - 6).ToUpper() + ",原因:" + value);
        }
    }
}
复制代码

六、实现CommandBase<MySession, MyRequestInfo>:

复制代码
using SuperSocket.SocketBase.Command;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Utils;

namespace SuperSocketServer
{
    public class EC : CommandBase<MySession, MyRequestInfo>
    {
        public override void ExecuteCommand(MySession session, MyRequestInfo requestInfo)
        {
            LogHelper.Log("客户端 " + session.SessionID.Substring(session.SessionID.Length - 6).ToUpper() + " 发来消息:" + requestInfo.Body);
            byte[] bytes = ASCIIEncoding.UTF8.GetBytes("消息收到");
            session.Send(bytes, 0, bytes.Length);
        }
    }
}
复制代码

七、服务端Form1.cs代码:

复制代码
using SuperSocket.SocketBase.Config;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Utils;

namespace SuperSocketServer
{
    public partial class Form1 : Form
    {
        private MyServer _myServer;

        public Form1()
        {
            InitializeComponent();
            LogHelper.Init(this, txtLog);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _myServer = new MyServer();
            ServerConfig serverConfig = new ServerConfig()
            {
                Port = 2021
            };
            _myServer.Setup(serverConfig);
            _myServer.Start();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            foreach (MySession session in _myServer.GetAllSessions())
            {
                byte[] bytes = ASCIIEncoding.UTF8.GetBytes("服务端广播消息");
                session.Send(bytes, 0, bytes.Length);
            }
        }
    }
}
复制代码

八、客户端Form1.cs代码:

复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SuperSocketClient
{
    public partial class Form1 : Form
    {
        private Socket _socket;

        private NetworkStream _socketStream;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            EndPoint serverAddress = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2021);
            _socket = new Socket(serverAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            _socket.Connect(serverAddress);
            _socketStream = new NetworkStream(_socket);

            //SocketAsyncEventArgs socketAsyncArgs = new SocketAsyncEventArgs();
            //byte[] buffer = new byte[10240];
            //socketAsyncArgs.SetBuffer(buffer, 0, buffer.Length);
            //socketAsyncArgs.Completed += ReciveAsync;
            //_socket.ReceiveAsync(socketAsyncArgs);

            Receive(_socket);

        }

        private void button1_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                Random rnd = new Random();
                string cmd = "EC";
                string msg = "测试消息00" + rnd.Next(0, 100).ToString("00");
                Send(cmd, msg);
            });
        }

        public void Send(string cmd, string msg)
        {
            byte[] cmdBytes = Encoding.ASCII.GetBytes(cmd);
            byte[] msgBytes = Encoding.UTF8.GetBytes(msg);
            byte[] lengthBytes = BitConverter.GetBytes((short)msgBytes.Length);

            _socketStream.Write(cmdBytes, 0, cmdBytes.Length);
            _socketStream.Write(lengthBytes, 0, lengthBytes.Length);
            _socketStream.Write(msgBytes, 0, msgBytes.Length);
            _socketStream.Flush();
            Log("发送:" + msg);
        }

        private void ReciveAsync(object obj, SocketAsyncEventArgs e)
        {
            if (e.BytesTransferred > 0)
            {
                string data = ASCIIEncoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred);
                Log("接收:" + data);
            }
        }

        private void Receive(Socket socket)
        {
            Task.Factory.StartNew(() =>
            {
                try
                {
                    while (true)
                    {
                        byte[] buffer = new byte[10240];
                        int receiveCount = _socket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                        if (receiveCount > 0)
                        {
                            string data = ASCIIEncoding.UTF8.GetString(buffer, 0, receiveCount);
                            Log("接收:" + data);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log("Receive出错:" + ex.Message + "\r\n" + ex.StackTrace);
                }
            }, TaskCreationOptions.LongRunning);
        }

        #region Log
        /// <summary>
        /// 输出日志
        /// </summary>
        private void Log(string log)
        {
            if (!this.IsDisposed)
            {
                this.BeginInvoke(new Action(() =>
                {
                    txtLog.AppendText(DateTime.Now.ToString("HH:mm:ss.fff") + " " + log + "\r\n\r\n");
                }));
            }
        }
        #endregion

    }
}
复制代码

辅助工具类LogHelper:

复制代码
using SuperSocketServer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Utils
{
    public class LogHelper
    {
        private static Form1 _frm;

        private static TextBox _txtLog;

        public static void Init(Form1 frm, TextBox txt)
        {
            _frm = frm;
            _txtLog = txt;
        }

        /// <summary>
        /// 输出日志
        /// </summary>
        public static void Log(string log)
        {
            if (!_frm.IsDisposed)
            {
                _frm.BeginInvoke(new Action(() =>
                {
                    _txtLog.AppendText(DateTime.Now.ToString("HH:mm:ss.fff") + " " + log + "\r\n\r\n");
                }));
            }
        }

    }
}
复制代码

测试截图:

问题:

1、客户端使用SocketAsyncEventArgs异步接收数据,第一次能收到数据,后面就收不到了,不知道什么原因,同步接收数据没问题

2、SuperSocket源码中的示例和网上相关的博客,客户端要么是原生Socket实现,要么是Socket调试工具,客户端不需要复杂一点的功能或数据结构吗?客户端不需要解包吗?SuperSocket不能用来写客户端吗?

 

出处:

https://www.cnblogs.com/s0611163/p/15193345.html


相关教程