上一篇文章,咱們瞭解了客戶端如何與服務器建立WebSocket鏈接。可是一個巴掌拍不響,既然是通訊,就必然最少要有兩個端。今天咱們來看看c#如何用已有的框架實現一個WebSocket服務端。web
在.Net Framework 4.5及以上版本中,微軟爲咱們集成了WebSocket協議的基本實現。微軟提供的WebSocket對象位於System.Net.WebSocket命名空間下,使用起來挺繁瑣的,因此我選擇了SuperWebSocket框架來簡化開發的難度。c#
SuperWebSocket框架能夠經過NuGet直接獲取並引用到項目中,也能夠在http://superwebsocket.codeplex.com/中下載最新的DLL服務器
咱們來看SuperWebSocket如何咱們快速搭建一個服務端websocket
WebSocketServer wsServer = new WebSocketServer(); if (!wsServer.Setup("127.0.0.1", 2012)) { //設置IP 與 端口失敗 一般是IP 和端口範圍不對引發的 IPV4 IPV6 } if (!wsServer.Start()) { //開啓服務失敗 基本上是端口被佔用或者被 某殺毒軟件攔截形成的 return; } wsServer.NewSessionConnected += (session) => { //有新的鏈接 }; wsServer.SessionClosed += (session, reason) => { //有斷開的鏈接 }; wsServer.NewMessageReceived += (session, message) => { //接收到新的文本消息 }; wsServer.NewDataReceived += (session, bytes) => { //接收到新的二進制消息 }; Console.ReadKey(); wsServer.Stop();
這裏WebSocketServer對象經過Setup方式對要偵聽的IP及端口進行了設置。而後使用Start方法啓動偵聽。session
Setup方法有4種重載,可是咱們一般用到的只有設置IP和端口,IP爲string類型,若是傳入的字符串沒法被轉換爲支持的IP格式,Setup方法會返回false表示設置失敗。框架
WebSocketServer還提供了4個事件用以管理與客戶端的鏈接、斷開、和接受消息動做。新版本的WebSocket支持傳送的數據格式有 「文本」 和 「二進制」兩種,NewMessageReceived事件用於處理文本類型的消息,NewDataReceived事件用於處理二進制類型的消息。socket
到這裏 咱們已經成功的搭建了一個實現了WebSocket協議的服務端了。至於服務端的寄宿方式有不少,SuperWebSocket框架支持以 控制檯、Winform、IIS以及Windows服務的形式寄宿服務,不過網上不少資料都不建議在IIS中寄宿服務,聽說是由於寄宿在IIS中性能比較低。ide
WebSocket既然是雙工通訊,那麼咱們就不能光等着接收來自客戶端的消息, 咱們也須要從服務端向客戶端「推送」消息,如今咱們來看如何由服務端向客戶端發送消息。性能
SuperWebSocket框架中,服務端與客戶端建立的鏈接對象爲WebSocketSession類型,也就是說它將每個客戶端的實例視爲一個會話,在客戶端建立鏈接的時候,產生這個會話,在客戶端斷開鏈接的時候,銷燬這個會話,而客戶端與服務端進行消息通訊的時候,也依賴這個會話進行傳遞。咱們要實現服務器端向客戶端的廣播,就要獲取到當前正在活動的全部會話,咱們經過代碼來看如何獲取全部的會話學習
wsServer.GetAllSessions() //獲取全部的會話 已斷開的會話不會出如今集合中
很簡單吧,在獲取到活動的會話以後 咱們就能夠向客戶端發送消息了,這裏咱們讓服務器向客戶端定時發送服務器時間
Timer timer = new Timer((data) => { var msg = string.Format("服務器當前時間:{0:HH:MM:ss}", DateTime.Now); //對當前已鏈接的全部會話進行廣播 foreach (var session in wsServer.GetAllSessions()) { session.Send(msg); } }, null, 1000, 1000);
這樣 全部與服務端保持鏈接的客戶端就均可以接受到來自服務器端的消息了。
在這個例子裏 咱們看到了全部的消息都是由會話對象發出的,會話對象Send的消息 也支持「文本」與「二進制兩種形式,同時會話對象還提供一個SendCloseHandshakeResponse()方法向客戶端發送一個強制斷開鏈接的指令。
WebSocketSession對象包含了服務端和客戶端的全部信息,以及WebSocketServer對象自己,咱們能夠利用它作不少事情,下邊咱們就來實現一個簡單的聊天室。至於聊天室的原理 就是一我的將要說的話發送到服務器,再由服務器廣播給在這個聊天室裏的全部人看到。恩 就這麼簡單。咱們來上代碼,多了不解釋,至關簡單。
public class ChatWebSocket { private const string ip = "127.0.0.1"; private const int port = 2014; private WebSocketServer ws = null;//SuperWebSocket中的WebSocketServer對象 public ChatWebSocket() { ws = new WebSocketServer();//實例化WebSocketServer //添加事件偵聽 ws.NewSessionConnected += ws_NewSessionConnected;//有新會話握手並鏈接成功 ws.SessionClosed += ws_SessionClosed;//有會話被關閉 多是服務端關閉 也多是客戶端關閉 ws.NewMessageReceived += ws_NewMessageReceived;//有客戶端發送新的消息 } void ws_NewSessionConnected(WebSocketSession session) { Console.WriteLine("{0:HH:MM:ss} 與客戶端:{1}建立新會話", DateTime.Now, GetSessionName(session)); var msg = string.Format("{0:HH:MM:ss} {1} 進入聊天室", DateTime.Now, GetSessionName(session)); SendToAll(session, msg); } void ws_SessionClosed(WebSocketSession session, SuperSocket.SocketBase.CloseReason value) { Console.WriteLine("{0:HH:MM:ss} 與客戶端:{1}的會話被關閉 緣由:{2}", DateTime.Now, GetSessionName(session), value); var msg = string.Format("{0:HH:MM:ss} {1} 離開聊天室", DateTime.Now, GetSessionName(session)); SendToAll(session, msg); } void ws_NewMessageReceived(WebSocketSession session, string value) { var msg = string.Format("{0:HH:MM:ss} {1}說: {2}", DateTime.Now, GetSessionName(session), value); SendToAll(session, msg); } /// <summary> /// 啓動服務 /// </summary> /// <returns></returns> public void Start() { if (!ws.Setup(ip, port)) { Console.WriteLine("ChatWebSocket 設置WebSocket服務偵聽地址失敗"); return; } if (!ws.Start()) { Console.WriteLine("ChatWebSocket 啓動WebSocket服務偵聽失敗"); return; } Console.WriteLine("ChatWebSocket 啓動服務成功"); } /// <summary> /// 中止偵聽服務 /// </summary> public void Stop() { if (ws != null) { ws.Stop(); } } private string GetSessionName(WebSocketSession session) { //這裏用Path來取Name 不太科學…… return HttpUtility.UrlDecode(session.Path.TrimStart('/')); } private void SendToAll(WebSocketSession session, string msg) { //廣播 foreach (var sendSession in session.AppServer.GetAllSessions()) { sendSession.Send(msg); } } }
關與SuperWebSocket的基本使用就介紹到這裏了……頂着老闆不時窺屏的壓力,可能文章有點語無倫次,但願你們多多體諒,也但願你們提出寶貴意見 共同窗習。下一篇我會考慮介紹「子協議」和SuperWebSocket提供的Json字符串類型數據的處理
示例代碼在這裏 下載
提示:
SuperSocket與SuperWebSocket框架都是Kerry Jiang的項目 SuperSocket最新版本號是1.6 SuperWebSocket最新版本號是0.8 以前一直覺得第一個是官網的……後來查了下資料不是……第一個框架BUG海多……這裏給你們提個醒……
本系列本月暫停更新………這個框架資料不多……並且有點坑……在死磕探路中……