SuperSocket服务端与客户端搭建

本文记录使用SuperSocket搭建Socket服务端,然后搭建客户端与之通信

环境:.Net 4.5

 

一、先说服务端

创建一个控制台SuperSocketServer,创建会话类:MyServerSession

public   class MyServerSession:AppSession<MyServerSession>
    {
        public override void Send(string message)
        {
            Console.WriteLine("发送消息:"+message);
            base.Send(message);
        }
        protected override void OnSessionStarted()
        {
            Console.WriteLine("Session已启动" );
            base.OnSessionStarted();
        }
        protected override void OnInit()
        {
            this.Charset = Encoding.GetEncoding("gb2312");
            base.OnInit();
        }

       protected override void HandleUnknownRequest(StringRequestInfo requestInfo)
        {
            Console.WriteLine("未知请求");
            base.HandleUnknownRequest(requestInfo);
        }
    }

分别表示4个状态和动作,一看就明白。

然后创建服务类:MyServer

public class MyServer:AppServer<MyServerSession>
  {
      protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
      {
          Console.WriteLine("正在准备配置文件");
          return base.Setup(rootConfig, config);
      }
      protected override void OnStarted()
      {
          Console.WriteLine("服务已启动");
          base.OnStarted();
      }
      protected override void OnStopped()
      {
          Console.WriteLine("服务已停止");
          base.OnStopped();
      }
      protected override void OnNewSessionConnected(MyServerSession session)
      {
          Console.WriteLine("新链接进入:" + session.LocalEndPoint.Address.ToString() +":"+ session.RemoteEndPoint.Port + "(" + session.SessionID + ")" + ",时间:" + DateTime.Now);
          base.OnNewSessionConnected(session);
      }
      protected override void OnSessionClosed(MyServerSession session, CloseReason reason)
      {
          Console.WriteLine("链接关闭:" + session.LocalEndPoint.Address.ToString() + ":" + session.RemoteEndPoint.Port + "(" + session.SessionID + ")" + ",时间:" + DateTime.Now);
          base.OnSessionClosed(session, reason);
      }
  }

表示服务器的4个状态,这些状态可以根据业务进行扩展

再创建命令类:ECHO执行客户端的命令

public  class ECHO: CommandBase<MyServerSession, StringRequestInfo>
     {
         public override void ExecuteCommand(MyServerSession session, StringRequestInfo requestInfo)
         {
             if (requestInfo.Parameters.Length < 2)
                 return;
             string cmd = requestInfo.Parameters[0];
             switch (cmd)
             {
                 case "heart":// heart 2
                     session.Send("ok");
                     break;
                 case "hello":// hello 2
                     session.Send("你说:"+ requestInfo.Parameters[1]);
                     break;
                 case "login":// login 我 000 000
                     string userID = requestInfo.Parameters[1];
                     Console.WriteLine(userID + "登录成功");
                     break;
                 case "sendto"://sendto 我ID 他ID 内容
                     rev.Send(requestInfo.Parameters[3]);
                     Console.WriteLine(string.Format("{0}对{1}说:{2}", requestInfo.Parameters[1],requestInfo.Parameters[2], requestInfo.Parameters[3]));
                     break;
                 default:
                     break;
             }
             if (requestInfo.Parameters[0] == "all")
             {
                 var sessions = session.AppServer.GetAllSessions();
                 foreach (var item in sessions)
                 {
                     item.Send(requestInfo.Body);
                 }
             }

            //根据参数个数或者其他条件判断,来进行一些自己的操作
             //if (requestInfo.Parameters.Length == 2)
             //{
             //    Console.WriteLine("调用成功");
             //    session.Send(string.Format("{0}:{1},已经成功接收到你的请求\r\n", session.RemoteEndPoint.Address, session.RemoteEndPoint.Port));
             //}
             //else
             //{
             //    session.Send("参数不正确\r\n");
             //}
             //session.Send(requestInfo.Body);
         }

     }

这个类里面列举了执行动作判断,消息群发,一对一发,当然叶可以一对多

最后是启动服务main

static void Main(string[] args)
{
     IBootstrap bootstrap = BootstrapFactory.CreateBootstrap();
     if (!bootstrap.Initialize())
     {
         Console.WriteLine(DateTime.Now + ":Socket初始化失败\r\n");
         return;
     }

    var result = bootstrap.Start();
     foreach (var server in bootstrap.AppServers)
     {
         if (server.State == ServerState.Running)
         {
             Console.WriteLine(DateTime.Now + ":serverName为:" + server.Name + "Socket运行中\r\n");
             Console.Read();
         }
         else
         {
             Console.WriteLine(DateTime.Now + ":serverName为:" + server.Name + "Socket启动失败\r\n");
         }
     }
}

也是一看就能明白,还有配置文件:

<configuration>
<configSections>
<!--log 日志记录-->
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
<!--SocketEngine-->
<section name="superSocket" type="SuperSocket.SocketEngine.Configuration.SocketServiceConfig, SuperSocket.SocketEngine" />
</configSections>
     <!--配置SocketServer路径-->
     <superSocket>
         <servers>
             <server name="MySocket" textEncoding="gb2312"
                     serverType="SuperSocketServer.MyServer, SuperSocketServer"
                    ip="Any" port="2018" maxConnectionNumber="100">
             </server>
         </servers>
     </superSocket>

    <startup>
         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
     </startup>
</configuration>

全部的引用是这几个:

image


二、再说客户端

目前代码较为简单,实现了心跳与断线重连

class Program
{
     private static AsyncTcpSession client;
     static System.Timers.Timer timer = null;
     private int port = 2018;

    static void Main(string[] args)
     {
         new Program().Link();
         string input = Console.ReadLine();
         while (input != "exit"&& !string.IsNullOrEmpty(input))
         {
             if (client != null && client.IsConnected)
             {
                 var msg = System.Text.Encoding.Default.GetBytes("echo hello " + input + "\r\n");
                 client.Send(msg,0, msg.Length);
                 input = Console.ReadLine();
             }

        }
     }
     private void Link()
     {
         client = new AsyncTcpSession();
         client.Connected += OnClientConnected;
         client.Error += OnClientError;
         client.Closed += OnClientClosed;
         // 收到服务器数据事件
         client.DataReceived += client_DataReceived;

        //每10s发送一次心跳或尝试一次重连
         timer = new System.Timers.Timer(10000);
         timer.Elapsed += new System.Timers.ElapsedEventHandler((s, x) =>
         {
             //心跳包
             if (client.IsConnected)
             {
                 var heartMsg = System.Text.Encoding.Default.GetBytes("echo heart 2\r\n");
                 client.Send(heartMsg,0, heartMsg.Length);
             }
             //断线重连
             else if (!client.IsConnected)
             {
                 client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), port));
             }
         });
         timer.Enabled = true;
         timer.Start();

    }
     private void OnClientConnected(object sender, EventArgs e)
     {
         Console.WriteLine("已连接" + '\n');
     }
     private void OnClientClosed(object sender, EventArgs e)
     {
         Console.WriteLine("已断开" + '\n');
     }
     private void OnClientError(object sender, ErrorEventArgs e)
     {
         Console.WriteLine($"错误:{e.Exception.Message}" + '\n');
     }
     void client_DataReceived(object sender, DataEventArgs e)
     {
         string msg = Encoding.Default.GetString(e.Data);
         Console.WriteLine(msg.Trim('\0'));
     }
}

引用如下:

image

 

控制台版代码下载,压缩包里面带了tcptool可以不用客户端测试,记得每个命令完了要敲回车

Winform版代码下载

posted @ 2021-12-26 16:51  石曼迪  Views(2288)  Comments(0Edit  收藏  举报
瓴域建设-环保事业中心