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版代碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM