.NET下使用socket.io隨筆記錄

dotNET跨平臺發表於2018-02-24

一、問題背景

目前公司在網際網路產品上需要程式與前端部分要進行一個實時互動,在進行一定程度上的選型後,決定使用socket.io框架進行一個實踐,算是公司的一個新的 嘗試,也算是給自己增加增長見聞,由於我是做後端以及桌面程式開發,所以前端部分就不細聊,主要是針對桌面程式如何連線socket.io進行一個嘗試

二、基本邏輯圖

640?wx_fmt=png&wxfrom=5&wx_lazy=1

  本地應用程式:部署在區域網內(可以聯通外網),主要負責相關資料獲取

  Web瀏覽器端:跟本地應用程式不是處於同一個網路,請求發起方

  中轉服務(重點):中轉服務整合認證功能,必須經過認證的客戶端才允許進行連線,並且對於客戶端要有唯一指定的ID進行連線操作

  整體思路如以上的流程圖,由Web瀏覽器端開始發起請求,Web瀏覽器端通過連線中轉服務,將資訊傳送給指定的本地應用程式,應用程式處理完成後,將結果通過原路徑進行一個反饋

二、客戶端程式開發

  客戶端SDK採用SocketIoClientDotNet,這是一個github上開源的,可以連線socket.io的客戶端,支援.net 3.5及以上,可以方便的幫助我們進行連線socket.io的開發

Socket  socket = IO.Socket("ws://192.168.7.4:3000", new IO.Options()

           {

               Reconnection = true,

               Cookies = new Dictionary<string, string>() { { "companyId", GlobalStatic.COMPANY.COMPANY_ID }, { "userId", GlobalStatic.UserDomain.user.USER_ID } },

               Timeout = 60000,

               ReconnectionDelay = 1000,

 

               Transports = new List<string>() { "websocket" },

               Path ="heart"

           });

 

           socket.On(Socket.EVENT_CONNECT, () =>

           {

 

               JObject jObject = JObject.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(new

               {

                   companyId = GlobalStatic.COMPANY.COMPANY_ID,

                   token = GlobalStatic.TOKEN,

                   hostId = GlobalStatic.HOST_ID,

                   hostName = GlobalStatic.HOST_NAME,

                   printerNames = GlobalStatic.HOSTINFO.PrinterName,

                   source = "assistant",

                   userId = GlobalStatic.UserDomain.user.USER_ID

               }));

               socket.Emit("authentication", jObject);

               Debug.WriteLine("authentication");

           });

           socket.On(Socket.EVENT_DISCONNECT, (data) =>

           {

               Debug.WriteLine("心跳斷開連線" + data);

               flag = false;

               OnConnectionStatus?.Invoke(flag);

               socket.Disconnect();

           });

           socket.On("authenticated", (obj) =>

           {

               flag = true;

               OnConnectionStatus?.Invoke(flag);

               Debug.WriteLine("心跳認證成功:" + obj);

           });

           socket.On("unauthorized", (obj) =>

           {

               Debug.WriteLine("心跳認證失敗" + obj);

               socket.Disconnect();

           });

SocketIoClientDotNet注意點:

  1. emit的資料必須為字串或者JObject(Newtonsoft.Json中的)

  2. 從實際情況來看,內部每個On的監聽都是維護了一個執行緒,所有如果是不想要阻塞的話,那在on的方法中還需要自己起執行緒去完成

  3. 如果不在options中設定AutoConnect=false的話,那例項化socket成功之後就會進行connect動作

三、關於SocketIoClientDotNet坑的問題

  在實際的使用過程中,偶然發現在程式開了很久 之後,執行緒數會一直增多,嘗試調節各種引數都毫無作用,最後只能無奈的跟蹤原始碼部分,在Thread資料夾下找到Heartbeat_net35.cs檔案中,發現run方法裡的while一直無法跳出去,並且註冊DoWork越來越多,如下所示,導致執行緒越來越多,目前解決辦法是將該程式碼註釋掉,還沒發現什麼問題,如果有哪位知道這段程式碼作用的話,望告知,謝謝

using System;

using System.ComponentModel;

using System.Threading;

 

namespace Quobject.EngineIoClientDotNet.Thread

{

    public class Heartbeat

    {

        private volatile bool gotHeartbeat = false;

        private BackgroundWorker heartBeatTimer= new BackgroundWorker();

        private CancellationTokenSource ts;

 

        private Heartbeat()

        {

            ts = new CancellationTokenSource();

        }

 

        public static Heartbeat Start(Action onTimeout, int timeout)

        {

            Heartbeat heartbeat = new Heartbeat();

            heartbeat.Run(onTimeout, timeout);

            return heartbeat;           

        }

 

        public void OnHeartbeat()

        {

            gotHeartbeat = true;

        }

 

        private void Run(Action onTimeout, int timeout)

        {

            heartBeatTimer = new BackgroundWorker();

 

            heartBeatTimer.DoWork += (s, e) =>

            {

               while (!ts.IsCancellationRequested)

               {

                    System.Threading.Thread.Sleep(timeout);

                    if (!gotHeartbeat && !ts.IsCancellationRequested)

                    {

                        onTimeout();

                        break;

                    }

                }

            };

 

            heartBeatTimer.RunWorkerAsync();

        }

 

        public void Stop()

        {

            ts.Cancel();

        }

    }

}

原文地址: http://www.cnblogs.com/OMango/p/8443395.html


.NET社群新聞,深度好文,歡迎訪問公眾號文章彙總 http://www.csharpkit.com

640?wx_fmt=jpeg

相關文章