.NET下使用socket.io随笔记录

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.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注意点:

  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();

        }

    }

}


以上是关于.NET下使用socket.io随笔记录的主要内容,如果未能解决你的问题,请参考以下文章

在nodejs中使用socket.io和net socket

关于Socket.IO的知识点记录

如何使用 socket.io 断开所有套接字服务端?

使用 socket.io 在 Node.js 中使用 MySql 数据库进行 HTML5 页面日志记录

socket.io 未定义并拒绝连接

与 .Net 兼容的 Socket.IO 示例