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

1、問題背景html

目前公司在互聯網產品上須要程序與前端部分要進行一個實時交互,在進行必定程度上的選型後,決定使用socket.io框架進行一個實踐,算是公司的一個新的 嘗試,也算是給本身增長增加見聞,因爲我是作後端以及桌面程序開發,因此前端部分就不細聊,主要是針對桌面程序如何鏈接socket.io進行一個嘗試
前端

2、基本邏輯圖git

  本地應用程序:部署在局域網內(能夠聯通外網),主要負責相關數據獲取github

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

  中轉服務(重點):中轉服務集成認證功能,必須通過認證的客戶端才容許進行鏈接,而且對於客戶端要有惟一指定的ID進行鏈接操做docker

  總體思路如以上的流程圖,由Web瀏覽器端開始發起請求,Web瀏覽器端經過鏈接中轉服務,將信息發送給指定的本地應用程序,應用程序處理完成後,將結果經過原路徑進行一個反饋後端

2、客戶端程序開發瀏覽器

  客戶端SDK採用SocketIoClientDotNet,這是一個github上開源的,能夠鏈接socket.io的客戶端,支持.net 3.5及以上,能夠方便的幫助咱們進行鏈接socket.io的開發websocket

 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動做

3、關於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後臺開發,開始接觸微服務、docker等互聯網相關

本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出, 原文連接 若有問題, 可郵件(hongjb@yizit.com)諮詢.

相關文章
相關標籤/搜索