超詳細的TCP、Sokcket和SuperSocket與TCP入門指導
前言
本文主要介紹TCP、Sokcket和SuperSocket的基礎使用。
建立例項模式的SuperSocket服務
首先建立控制檯專案,然後Nuget新增引用SuperSocket.Engine。
然後編寫服務程式碼,SuperSocket的服務程式碼主要是配置AppServer物件,因為AppServer已經很好的封裝埠監聽了。
程式碼如下所示:
class Program { static AppServer appServer { get; set; } static void Main(string[] args) { var serverConfig = new SuperSocket.SocketBase.Config.ServerConfig(); serverConfig.Port = 5180; serverConfig.TextEncoding = "gb2312"; serverConfig.MaxConnectionNumber = 1000; appServer = new AppServer(); //配置 if (!appServer.Setup(serverConfig)) { Console.WriteLine("配置失敗!"); return; } //啟動 if (!appServer.Start()) { Console.WriteLine("啟動失敗!"); return; } Console.WriteLine("啟動成功,按Q退出!"); appServer.NewSessionConnected += new SessionHandler<AppSession>(appServer_NewSessionConnected); appServer.SessionClosed += appServer_NewSessionClosed; appServer.NewRequestReceived += new RequestHandler<AppSession, StringRequestInfo>(appServer_NewRequestReceived); while (Console.ReadKey().KeyChar != 'q') { continue; } //停止 appServer.Stop(); Console.WriteLine("服務已停止"); Console.ReadKey(); } static void appServer_NewSessionConnected(AppSession session) { var count = appServer.SessionCount; Console.WriteLine($"服務端得到來自客戶端的連線成功 ,當前會話數量:" + count); //這裡也可以向會話的stream裡寫入資料,如果在這裡向流寫入資料,則客戶端需要在Send之前先接收一次,不然的話,Send後接收的就是這條資料了 session.Send("連線成功"); } static void appServer_NewSessionClosed(AppSession session, CloseReason aaa) { var count = appServer.SessionCount; Console.WriteLine($"服務端 失去 來自客戶端的連線" + session.SessionID + aaa.ToString()+ " 當前會話數量:" + count); } static void appServer_NewRequestReceived(AppSession session, StringRequestInfo requestInfo) { Console.WriteLine($"Key:" + requestInfo.Key + $" Body:" + requestInfo.Body); session.Send("我是返回值:" + requestInfo.Body); } }
AppServer:AppServer是SuperSocket中定義的Socket服務類,他替我們實現了複雜的埠監聽,不用再寫While迴圈,不用再關心執行緒阻塞的問題,在監聽埠在這裡,我們只要呼叫AppServer的物件的Start方法,就可以了;AppServer還提供了一個配置檔案類—ServerConfig,通過它,我們可以配置具體監聽的埠、併發數量、編碼、最大傳輸位元組數、傳輸模式(TCP/UDP)等等屬性;此外還提供三個重要事件:會話連線啟動事件(NewSessionConnected)、會話關閉事件(SessionClosed)、請求接受事件(NewRequestReceived)。
注:文中在連線成功的事件中,我們向客戶端傳送訊息了,即,客戶端在連線後,傳送訊息前,需要接收該資訊。
建立TCP傳送訊息客戶端
服務建立後,我們建立客戶端。
程式碼如下所示:
static void Main(string[] args) { TCPConnect("127.0.0.1", 5180); Console.ReadKey(); } static void TCPConnect(String server, Int32 port) { string message = $"ADD kiba518 518" + "\r\n"; try { TcpClient client = new TcpClient(); client.Connect(server, port); Byte[] data = System.Text.Encoding.Default.GetBytes(message); String responseData = String.Empty; NetworkStream stream = client.GetStream(); byte[] buffer = new byte[1024 * 1024 * 2]; Int32 bytes = stream.Read(buffer, 0, buffer.Length); responseData = System.Text.Encoding.Default.GetString(buffer, 0, bytes); Console.WriteLine("接收伺服器在連線事件中寫入的資料: {0}", responseData); stream.Write(data, 0, data.Length); Console.WriteLine("傳送資料: {0}", message); data = new Byte[256]; bytes = stream.Read(buffer, 0, buffer.Length); responseData = System.Text.Encoding.Default.GetString(buffer, 0, bytes); Console.WriteLine("接收返回值: {0}", responseData); stream.Close(); client.Close(); } catch (ArgumentNullException e) { Console.WriteLine("ArgumentNullException: {0}", e.Message); } catch (SocketException e) { Console.WriteLine("SocketException: {0}", e.Message); } Console.Read(); }
程式碼很簡單,就是使用TcpClient連線伺服器的IP和埠,然後傳送訊息。
因為我們使用的SuperSocket,有格式要求,所以我們需要準守。
格式要求如下:
命令名稱+空格+引數+引數+...引數+"\r\n"
對應的字串如下:
$"ADD kiba518 518" + "\r\n"
因為上文中,服務在連線成功後就向客戶端傳送的流中寫入了資料,所以,我們在Send訊息前,先接收一下流中的資料。
客戶端與服務聯調
先執行服務,在執行客戶端,結果服務端與客戶端成功的完成了一次通訊,如下圖所示:
為了更清晰的瞭解通訊內容,我們在服務接收訊息事件中斷點,如下圖:
可以看到引數requestInfo完整的解析了我們傳送的字串【"ADD kiba518 518" + "\r\n"】。
建立配置模式的SuperSocket服務
現在我們建立一個配置模式的SuperSocket服務,這種模式客戶通過配置建立多個SuperSocket,即可以在一個專案裡通過配置監聽多個埠,這裡,我們只做一個埠監聽的配置例子。
與例項模式的開始一樣,先建立一個控制檯程式,然後Nuget新增引用SuperSocket.Engine。
然後進行三步操作。
一,編寫Main函式,啟動SuperSocket,通過啟動引導工廠BootstrapFactory例項化一個啟動引導物件,然後初始化化,該初始化會遍歷當前專案中所有繼承了AppServer的類,然後呼叫他們的Start方法,程式碼如下所示:
static void Main(string[] args) { #region 初始化Socket 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"); } else { Console.WriteLine(DateTime.Now + ":serverName為:" + server.Name + "Socket啟動失敗\r\n"); } } Console.ReadKey(); #endregion }
二,修改App.config配置檔案,在configuration節點下,增加superSocket的section,並配置superSocket,程式碼如下:
<configSections> <section name="superSocket" type="SuperSocket.SocketEngine.Configuration.SocketServiceConfig, SuperSocket.SocketEngine" /> </configSections> <!--配置SocketServer路徑--> <superSocket> <servers> <!-- serverType屬性有兩個引數,第一個是服務類的完全限定名,第二個是服務類的名稱空間 --> <server name="MySocket" textEncoding="gb2312" serverType="SuperSocketServerSessionMode.SocketServer, SuperSocketServerSessionMode" ip="Any" port="5180" maxConnectionNumber="100"> </server> </servers> </superSocket>
三,建立SocketServer類、SocketSession類、SocketCommand類。
SocketServer類:繼承泛型AppServer(其泛型類指定一個會話類)該類用於建立SuperSocket的服務並監聽埠;其Setup方法,預設讀取App.config配置檔案中的superSocket節點—servers節點—server節點;讀取時根據server的serverType屬性匹配讀取。
public class SocketServer : AppServer<SocketSession> { 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(SocketSession session) { Console.WriteLine("新的連線地址為" + session.LocalEndPoint.Address.ToString() + ",時間為" + DateTime.Now); base.OnNewSessionConnected(session); } }
SocketSession類:繼承AppSession,是SuperSocket的會話類。
如果客戶端所傳送的訊息不合法,則會被會話的HandleUnknownRequest函式截獲,如果合法,則傳送到指定的命令類中。
程式碼如下:
public class SocketSession : AppSession<SocketSession> { 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($"遇到未知的請求 Key:" + requestInfo.Key + $" Body:" + requestInfo.Body); base.HandleUnknownRequest(requestInfo); } }
SocketCommand類:是SuperSocket的命令類,定義明確的會話命令;類名即客戶端傳送訊息的第一個空格前的字串。
程式碼如下:
public class SocketCommand : CommandBase<SocketSession, StringRequestInfo> { public override void ExecuteCommand(SocketSession session, StringRequestInfo requestInfo) { //根據引數個數或者其他條件判斷,來進行一些自己的操作 Console.WriteLine($"呼叫成功 Key:" + requestInfo.Key + $" Body:" + requestInfo.Body); session.Send("已經成功接收到你的請求\r\n"); } }
建立配置模式的SuperSocket客戶端
建立一個配置模式的SuperSocket客戶端,這一次我們使用Socket類建立。
程式碼如下:
static Socket socketClient { get; set; } static void Main(string[] args) { socketClient = new Socket(SocketType.Stream, ProtocolType.Tcp); IPAddress ip = IPAddress.Parse("127.0.0.1"); IPEndPoint point = new IPEndPoint(ip, 5180); socketClient.Connect(point); Thread thread = new Thread(Recive); //不停的接收伺服器端傳送的訊息 thread.Start(); Thread thread2 = new Thread(Send);//不停的給伺服器傳送資料 thread2.Start(); } static void Recive() { while (true) { //獲取傳送過來的訊息 byte[] buffer = new byte[1024 * 1024 * 2]; var effective = socketClient.Receive(buffer); if (effective == 0) { break; } var str = Encoding.Default.GetString(buffer, 0, effective); Console.WriteLine("伺服器 --- " + str); Thread.Sleep(2000); } } static void Send() { int i = 0;int param1 = 0;int param2 = 0; while (true) { i++;param1 = i + 1;param2 = i + 2; Console.WriteLine($"Send i:{i} param1:{param1} param2:{param2}"); string msg = $"SocketCommand {param1} {param2}" + "\r\n"; Console.WriteLine($"msg:{msg}"); var buffter = Encoding.Default.GetBytes(msg); var temp = socketClient.Send(buffter); Console.WriteLine($"Send 傳送的位元組數:{temp} "); Thread.Sleep(1000); } }
可以看到Socket的使用方式與Tcp的使用方式幾乎相同,都是指定IP和埠號,只是Socket多了一步,需要指定協議型別ProtocolType,這裡我們指定了是TCP。
客戶端與服務聯調
先執行服務,在執行客戶端,結果通訊成功,如下圖所示:
----------------------------------------------------------------------------------------------------
到此TCP、Sokcket和SuperSocket的基本使用已經介紹完了,程式碼已經傳到Github上了,歡迎大家下載。
程式碼已經傳到Github上了,歡迎大家下載。
Github地址: https://github.com/kiba518/SuperSocketConsole
----------------------------------------------------------------------------------------------------
注:此文章為原創,任何形式的轉載都請聯絡作者獲得授權並註明出處!
若您覺得這篇文章還不錯,請點選下方的【推薦】,非常感謝!
https://www.cnblogs.com/kiba/p/13728088.html
&n