關於WebSocket其實很早就想發了,奈何以前項目中的WebSocket的後端不是我作的,而我又想先後端都發出來和你們討論討論~因而擠出點時間研究了一下WebSocket的後端實現(因此纔有了這篇文章)。前端
首先是概念導論,如今你們在百度、谷歌很容易就能搜索到一大堆這樣的socket(百度百科)、Socket詳解(太多了就不一一列舉)web
看過這些概念導論之後,咱們準備先實現WebSocket的服務端(基礎概念都沒掌握的童鞋們須要補課了)。後端
說到.net的WebSocket實現,就不得不說SuperSocket,你能夠點擊這裏瞭解和下載它。session
看過上面連接之後,你應該知道它是有多好用的工具,接下來咱們就能夠搭建咱們的WebSocketServer了:架構
首先,建立一個窗體應用程序(winForm),固然你也能夠建立控制檯應用程序。socket
而後,須要將下載好的這幾個DLL引入你的項目中:SuperSocket.Common、SuperSocket.SocketBase、SuperSocket.SocketEngine、SuperWebSocket、log4net工具
其中SuperSocket相關類庫版本爲1.6,SuperWebSocket版本爲0.9,log4net爲1.2(版本錯誤可能會出一些誰也看不懂的碧油雞)。優化
接下來,咱們須要聲明一個webSocket對象,而且給它綁定好事件,好比這樣:ui
WebSocketServer ws = new WebSocketServer(); ws.NewMessageReceived += Ws_NewMessageReceived;//當有信息傳入時 ws.NewSessionConnected += Ws_NewSessionConnected;//當有用戶連入時 ws.SessionClosed += Ws_SessionClosed;//當有用戶退出時 ws.NewDataReceived += Ws_NewDataReceived;//當有數據傳入時 if (ws.Setup(10086))//綁定端口 ws.Start();//啓動服務
註釋標註的應該清楚,不過這裏我沒有對傳入數據作操做,各位看官能夠忽略不計。this
接下來咱們應該怎麼作呢?答案是重寫生成的事件方法。很容易看出咱們要先處理用戶連入和退出,而且保存和移除用戶信息(否則你都不知道你在和誰聊天),好比這樣:
Dictionary<WebSocketSession, string> userlist = new Dictionary<WebSocketSession, string>();//用戶列表
眼尖的同窗們必定發現了一個新類型:WebSocketSession,它是作什麼的呢?F12進去之後是這樣的:
貌似什麼都沒有?別急,咱們再看它的父類:
到這裏不少人就明白了,關於連入用戶的諸多信息都在這個類內,還提供了Send方法以便於Server端與之通信。
搞明白WebSocketSession類型能作什麼之後,就能夠針對不一樣操做進行響應了
客戶端在連入服務端時,須要發送一串信息來告訴服務端「who i am」,這時就須要動用Ws_NewMessageReceived事件的方法。
如:客戶端連入時,向服務端發送了「{'user':'001號學生','active':'login'}」,那麼咱們就能夠在服務端將該用戶的信息存儲至上面定義好的userlist中:
//添加至用戶集合的方法 public void AddUser(string UserName, WebSocketSession session) { userList.Add(session, UserName); } //login對應封裝dic方法 public Dictionary<string, string> login(Dictionary<string, string> Query, T curUser) { UserConnHandle userConn = () => { return Query["userid"]; }; Dictionary<string, string> Respon = new Dictionary<string, string>(); if (!service.userList.ContainsKey(curUser)) { if (Query["user"] == "" || Query["user"] == null) { Respon.Add("user", Guid.NewGuid().ToString().Replace("-", "")); } else { Respon.Add("userid", Query["userid"]); } Respon.Add("type", "1");//爲了前端更容易操做 Respon.Add("send", "0");//這裏0是告訴發給全部用戶仍是當前用戶 service.AddUser(Respon["user"], curUser);//將當前用戶添加至用戶集合 } return Respon; } //有新消息傳入時 private void Ws_NewMessageReceived(WebSocketSession session, string value) { Dictionary<string, string> res = login(value, session, this) as Dictionary<string, string>; switch (res["send"]) { case "0": res.Remove("send"); Send(res);//所有發送 break; case "1": res.Remove("send"); string username = res["to"]; WebSocketSession keys = userlist.Where(q => q.Value == username).Select(q => q.Key).First(); SendTo(keys, res);//針對發送 break; } }
這裏我封裝成dic只是爲了簡單調用,你們不習慣能夠封裝成別的(好比List<T>),下面是Send和SendTo:
//發送給全部用戶 public void Send(string msg) { foreach (var item in userList) { item.Key.Send(msg); } } //發送給單個用戶 public void SendTo(WebSocketSession session, string msg) { session.Send(msg); }
其實公聊就是給全部的連入用戶作個遍歷廣播,而私聊只須要針對某用戶廣播便可。
至此,基於SuperSocket實現的WebSocketServer就已經被簡單實現了。
本文中並無抽出接口,也沒有作IOC(實際項目上我是作了的),由於這樣寫你們更容易理解,後面的架構優化你們能夠自行發揮~
關於web客戶端對接,後面我會再出文章的(纔不要爛尾!)~~