.net下使用socket.io隨筆記錄
一、問題背景
目前公司在互聯網產品上需要程序與前端部分要進行一個實時交互,在進行一定程度上的選型後,決定使用socket.io框架進行一個實踐,算是公司的一個新的 嘗試,也算是給自己增加增長見聞,由於我是做後端以及桌面程序開發,所以前端部分就不細聊,主要是針對桌面程序如何連接socket.io進行一個嘗試
二、基本邏輯圖
本地應用程序:部署在局域網內(可以聯通外網),主要負責相關數據獲取
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註意點:
- emit的數據必須為字符串或者JObject(Newtonsoft.Json中的)
- 從實際情況來看,內部每個On的監聽都是維護了一個線程,所有如果是不想要阻塞的話,那在on的方法中還需要自己起線程去完成
- 如果不在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(); } } }
作者: Mango
出處: http://www.cnblogs.com/OMango/
關於自己:專註.Net桌面開發以及Web後臺開發,開始接觸微服務、docket等互聯網相關
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出, 原文鏈接 如有問題, 可郵件([email protected])咨詢.
.net下使用socket.io隨筆記錄