上一篇文章咱們使用原生的socket分別實現了服務器和客戶端,數組
本篇文章使用SuperSocket來開發實現服務器,服務器
以前也介紹了SuperSocket是一個輕量級, 跨平臺並且可擴展的 .Net/Mono Socket 服務器程序框架。你無須瞭解如何使用 Socket, 如何維護 Socket 鏈接和 Socket 如何工做,可是你卻可使用 SuperSocket 很容易的開發出一款 Socket 服務器端軟件,例如遊戲服務器,GPS 服務器, 工業控制服務和數據採集服務器等等。session
接下來開始咱們的開發,首先咱們須要安裝SuperSocket相關程序包,咱們新建一個項目開發SuperSocket服務器app
而後打開NuGet程序包管理器,搜索SuperSocket ,下載安裝SuperSocket和SuperSocket.Engine框架
下載安裝完畢後,咱們的項目中會自動引用了SuperSocke和log4net 相關程序集和配置文件socket
進入正題上代碼,咱們這裏只用SuperSocket作服務器端,客戶端使用SocketTool作測試ide
SocketTool工具
連接:https://pan.baidu.com/s/1ykEofUIZKE2yhe3mMyRbJw
提取碼:m2nk 測試
SuperSocket實現服務器:spa
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 }
先掛上官方說明文檔 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 }
接下來咱們開始測試,仍是默認使用3333端口,開啓監聽,咱們依舊是使用SocketTool工具建立三個客戶端,一塊兒訪問服務器
服務器:
客戶端
接下來三個客戶端分別以"9100"爲請求頭,test爲請求體給服務器發送數據,記住客戶端發送數據必定以回車換行爲結尾
客戶端:
服務器:
接下里測試服務器給客戶端,這裏以服務器給端口爲1083的客戶端發送數據"aaaa"
從客戶端列選擇端口號爲1083的客戶端,在textbox輸入aaaa 發送數據
服務器
客戶端
接下里客戶端關閉鏈接
服務器
到此,SuperSocket實現的服務器測試完美收官,其實SuperSocket的功能遠不止於此,我也只是剛開始使用
待後續研究官方文檔後什麼新的發如今更新,告辭!
感謝客觀閱讀,拜謝(抱拳~)
兩篇文章的源碼
原本想上傳GitHub的,畢竟這樣顯得專業一點,奈何初來乍到的,實在操做不了(留下了不懂英文的淚水),仍是放雲盤吧!
連接:https://pan.baidu.com/s/1zjCvkP2Ne9U3KR8vyBKhFw 提取碼:gee7