基於SuperSocket實現的WebSocket(后端)


關於WebSocket其實很早就想發了,奈何之前項目中的WebSocket的后端不是我做的,而我又想前后端都發出來和大家討論討論~於是擠出點時間研究了一下WebSocket的后端實現(所以才有了這篇文章)。

首先是概念導論,現在大家在百度、谷歌很容易就能搜索到一大堆這樣的socket(百度百科)Socket詳解(太多了就不一一列舉)

看過這些概念導論以后,我們准備先實現WebSocket的服務端(基礎概念都沒掌握的童鞋們需要補課了)。

 

說到.net的WebSocket實現,就不得不說SuperSocket,你可以點擊這里了解和下載它。

看過上面鏈接以后,你應該知道它是有多好用的工具,接下來我們就可以搭建我們的WebSocketServer了:

 

首先,創建一個窗體應用程序(winForm),當然你也可以創建控制台應用程序。

 

然后,需要將下載好的這幾個DLL引入你的項目中:SuperSocket.Common、SuperSocket.SocketBase、SuperSocket.SocketEngine、SuperWebSocket、log4net

其中SuperSocket相關類庫版本為1.6,SuperWebSocket版本為0.9,log4net為1.2(版本錯誤可能會出一些誰也看不懂的碧油雞)。

 

接下來,我們需要聲明一個webSocket對象,並且給它綁定好事件,比如這樣:

 

            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();//啟動服務            

 

注釋標注的應該清楚,不過這里我沒有對傳入數據做操作,各位看官可以忽略不計。

接下來我們應該怎么做呢?答案是重寫生成的事件方法。很容易看出我們要先處理用戶連入和退出,並且保存和移除用戶信息(不然你都不知道你在和誰聊天),比如這樣:

 

 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客戶端對接,后面我會再出文章的(才不要爛尾!)~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM