上一篇文章我們使用原生的socket分別實現了伺服器和客戶端, 本篇文章使用SuperSocket來開發實現伺服器, 之前也介紹了SuperSocket是一個輕量級, 跨平臺而且可擴展的 .Net/Mono Socket 伺服器程式框架。你無須瞭解如何使用 Socket, 如何維護 Socket 連 ...
上一篇文章我們使用原生的socket分別實現了伺服器和客戶端,
本篇文章使用SuperSocket來開發實現伺服器,
之前也介紹了SuperSocket是一個輕量級, 跨平臺而且可擴展的 .Net/Mono Socket 伺服器程式框架。你無須瞭解如何使用 Socket, 如何維護 Socket 連接和 Socket 如何工作,但是你卻可以使用 SuperSocket 很容易的開發出一款 Socket 伺服器端軟體,例如游戲伺服器,GPS 伺服器, 工業控制服務和數據採集伺服器等等。
接下來開始我們的開發,首先我們需要安裝SuperSocket相關程式包,我們新建一個項目開發SuperSocket伺服器
然後打開NuGet程式包管理器,搜索SuperSocket ,下載安裝SuperSocket和SuperSocket.Engine
下載安裝完畢後,我們的項目中會自動引用了SuperSocke和log4net 相關程式集和配置文件
進入正題上代碼,我們這裡只用SuperSocket做伺服器端,客戶端使用SocketTool做測試
SocketTool
鏈接:https://pan.baidu.com/s/1ykEofUIZKE2yhe3mMyRbJw
提取碼:m2nk
SuperSocket實現伺服器:

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 using System.Net.Sockets; 11 using System.Net; 12 using System.Threading; 13 using SuperSocket; 14 using SuperSocket.SocketBase; 15 using SuperSocket.SocketBase.Protocol; 16 17 namespace SuperSocket 18 { 19 public partial class SuperSocketServer : Form 20 { 21 public SuperSocketServer() 22 { 23 InitializeComponent(); 24 } 25 26 private void SuperSocketServer_Load(object sender, EventArgs e) 27 { 28 //txt_ip.Text = "127.0.0.1"; 29 txt_port.Text = "3333"; 30 } 31 32 //AppServer 代表了監聽客戶端連接,承載TCP連接的伺服器實例。理想情況下,我們可以通過AppServer實例獲取任何你想要的客戶端連接,伺服器級別的操作和邏輯應該定義在此類之中。 33 AppServer appServer; 34 //緩衝位元組數組 35 byte[] buffer = new byte[2048]; 36 37 string ipAddress_Connect; 38 string ipAddress_Close; 39 string ipAddress_Receive; 40 41 //存儲session和對應ip埠號的泛型集合 42 Dictionary<string, AppSession> sessionList = new Dictionary<string, AppSession>(); 43 44 enum OperateType 45 { 46 47 Add = 1, //添加 48 Remove = 2 //移除 49 } 50 51 /// <summary> 52 /// 開啟服務 53 /// </summary> 54 /// <param name="sender"></param> 55 /// <param name="e"></param> 56 private void btn_StartListen_Click(object sender, EventArgs e) 57 { 58 appServer = new AppServer(); 59 if (!appServer.Setup(int.Parse(txt_port.Text))) 60 { 61 SetMessage("Failed to Setup"); 62 return; 63 } 64 if (!appServer.Start()) 65 { 66 SetMessage("Failed to Start"); 67 return; 68 } 69 else 70 { 71 SetMessage("開啟監聽"); 72 } 73 //SuperSocket自定義了三個事件 ,連接事件,接收事件,關閉事件 74 appServer.NewSessionConnected += appServer_NewSessionConnected; 75 appServer.NewRequestReceived += appServer_NewRequestReceived; 76 appServer.SessionClosed += appServer_SessionClosed; 77 } 78 79 /// <summary> 80 /// 接收連接 81 /// </summary> 82 /// <param name="session"></param> 83 void appServer_NewSessionConnected(AppSession session) 84 { 85 //有新連接的時候,添加記錄 session.LocalEndPoint屬性獲取當前session的ip和埠號 86 //AppSession 代表一個和客戶端的邏輯連接,基於連接的操作應該定於在該類之中。你可以用該類的實例發送數據到客戶端,接收客戶端發送的數據或者關閉連接。 87 88 //獲取遠程客戶端的ip埠號 89 ipAddress_Connect = session.RemoteEndPoint.ToString(); 90 ComboboxHandle(ipAddress_Connect, OperateType.Add); 91 sessionList.Add(ipAddress_Connect, session); 92 SetMessage(ipAddress_Connect + "已連接!"); 93 } 94 95 /// <summary> 96 /// 接收數據 97 /// </summary> 98 /// <param name="session"></param> 99 /// <param name="requestInfo"></param> 100 void appServer_NewRequestReceived(AppSession session, StringRequestInfo requestInfo) 101 { 102 //requestInfo.Key 是請求的命令行用空格分隔開的第一部分 103 //requestInfo.Parameters 是用空格分隔開的其餘部分 104 //requestInfo.Body 是出了請求頭之外的所有內容 105 ipAddress_Receive = session.RemoteEndPoint.ToString(); 106 SetMessage("收到" + ipAddress_Receive + "數據: "+requestInfo.Key +" "+ requestInfo.Body); 107 } 108 109 /// <summary> 110 /// 關閉連接 111 /// </summary> 112 /// <param name="session"></param> 113 /// <param name="value"></param> 114 void appServer_SessionClosed(AppSession session, SocketBase.CloseReason value) 115 { 116 ipAddress_Close = session.RemoteEndPoint.ToString(); 117 ComboboxHandle(ipAddress_Close, OperateType.Remove); 118 sessionList.Remove(ipAddress_Close); 119 SetMessage(ipAddress_Close + "已關閉連接!"); 120 } 121 /// <summary> 122 /// 發送數據 123 /// </summary> 124 /// <param name="sender"></param> 125 /// <param name="e"></param> 126 private void btn_send_Click(object sender, EventArgs e) 127 { 128 //從客戶端列獲取想要發送數據的客戶端的ip和埠號,然後從sessionList中獲取對應session然後調用send()發送數據 129 if (cmb_socketlist.Items.Count != 0) 130 { 131 if (cmb_socketlist.SelectedItem == null) 132 { 133 MessageBox.Show("請選擇一個客戶端發送數據!"); 134 return; 135 } 136 else 137 { 138 sessionList[cmb_socketlist.SelectedItem.ToString()].Send(txt_send.Text); 139 } 140 } 141 else 142 { 143 SetMessage("當前沒有正在連接的客戶端!"); 144 } 145 txt_send.Clear(); 146 } 147 148 /// <summary> 149 /// 添加信息 150 /// </summary> 151 /// <param name="str"></param> 152 private void SetMessage(string str) 153 { 154 richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText(str + "\r\n"); })); 155 } 156 157 /// <summary> 158 /// combobox操作 159 /// </summary> 160 /// <param name="ipAddress"></param> 161 /// <param name="operateType">add 添加項/remove 移除項</param> 162 private void ComboboxHandle(string ipAddress, OperateType operateType) 163 { 164 if (operateType == OperateType.Add) 165 { 166 cmb_socketlist.Invoke(new Action(() => { cmb_socketlist.Items.Add(ipAddress); })); 167 } 168 if (operateType == OperateType.Remove) 169 { 170 cmb_socketlist.Invoke(new Action(() => { cmb_socketlist.Items.Remove(ipAddress); })); 171 } 172 } 173 174 } 175 }View Code
先掛上官方說明文檔 http://docs.supersocket.net/v1-6/zh-CN
這裡說明幾點:
(1)這裡appServer_NewRequestReceived(AppSession session, StringRequestInfo requestInfo)方法中的StringRequestInfo
是包含請求信息的,
requestInfo.Key 是請求的命令行用空格分隔開的第一部分
requestInfo.Parameters 是用空格分隔開的其餘部分,用空格分割開的字元串數組
requestInfo.Body 是出了請求頭之外的所有內容,是一個字元串
(2)這裡requestInfo是客戶端發送過來 嚴格按照 請求頭 請求參數 請求參數 請求參數 \r\n 的格式發送, 空格隔開的第一部分是請求頭,後邊用空格分割後組成的數據就是請求參數
而且必須是以回車換行結尾 SuperSocket才能正確接收;
(3)這裡請求頭和請求參數用什麼分割是可以自定義;我們可以自定義AppServer類,繼承APPServer類,然後使用下麵的代碼擴展命令行協議
比如用":"分割請求頭和請求參數,用","分隔請求參數.

1 public class YourServer : AppServer<YourSession> 2 { 3 public YourServer() 4 : base(new CommandLineReceiveFilterFactory(Encoding.Default, new BasicRequestInfoParser(":", ","))) 5 { 6 7 } 8 }View Code
接下來我們開始測試,還是預設使用3333埠,開啟監聽,我們依舊是使用SocketTool工具創建三個客戶端,一起訪問伺服器
伺服器:
客戶端
接下來三個客戶端分別以"9100"為請求頭,test為請求體給伺服器發送數據,記住客戶端發送數據一定以回車換行為結尾
客戶端:
伺服器:
接下里測試伺服器給客戶端,這裡以伺服器給埠為1083的客戶端發送數據"aaaa"
從客戶端列選擇埠號為1083的客戶端,在textbox輸入aaaa 發送數據
伺服器
客戶端
接下里客戶端關閉連接
伺服器
到此,SuperSocket實現的伺服器測試完美收官,其實SuperSocket的功能遠不止於此,我也只是剛開始使用
待後續研究官方文檔後什麼新的發現在更新,告辭!
兩篇文章的源碼
本來想上傳GitHub的,畢竟這樣顯得專業一點,奈何初來乍到的,實在操作不了(留下了不懂英文的淚水),還是放雲盤吧!
鏈接:https://pan.baidu.com/s/1zjCvkP2Ne9U3KR8vyBKhFw
提取碼:gee7