使用 WebSocket 封装成服务进行前后端通讯


[背景]
需要定时查询数据显示到前端,刚开始使用想到的是Ajax长轮询(这样子资源消耗太多了),然后百度,谷歌,发现Http 有一种新的请求方式

WebSocket

WebSocket 是什么?

在没有接触WebSocket之前,听说过 Socket ,那么 WebSocketSocket 到底是什么,他们二者关系有是什么?

WebSocket Socket 的关系--> 其实讨论这个点的的时候,我想到的 JavaJavascript 的关系,但是写文章不能靠自认为,于是我搜索了一下二者联系,发现很多博文都没有说明二者的关系,而是都在对比二者

长答案

当我们探讨两件事物的区别和联系时,我们想探讨些什么?

对于我来说,大多数情况是想知道两件事物本身,而并不是想只想了解「区别」本身。那么对这个问题最直接的解决方法应该是去了解Socket和WebSocket的来源和用法

那么它们的区别和联系就不言自明了。

WebSocket和Socket的区别 作者:TheAlchemist

所以, WebSocketSocket 没有可比性 -->划重点

介绍 一下 WebSocket && Socket

WebSocket

WebSocket 是为了满足基于 Web 的日益增长的实时通信需求而产生的(一次请求,终身连接-->这里有点问题,大家明白就好,我主要先说的就是比Ajax定时请求 消耗资源少 _)
在传统的 Web 中,要实现实时通信,通用的方式是采用 HTTP 协议不断发送请求(AJAX 定时请求)
但这种方式即浪费带宽(HTTP HEAD 是比较大的),又消耗服务器 CPU 占用(没有信息也要接受请求)


Socket

Socket可以有很多意思,和IT较相关的本意大致是指在端到端的一个连接中,这两个端叫做Socket。
对于IT从业者来说,它往往指的是TCP/IP网络环境中的两个连接端,大多数的API提供者(如操作系统,JDK)往往会提供基于这种概念的接口
所以对于开发者来说也往往是在说一种编程概念。同时,操作系统中进程间通信也有Socket的概念,但这个Socket就不是基于网络传输层的协议了

作者:TheAlchemist
链接:https://www.jianshu.com/p/59b5594ffbb0/
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

WebSocket Socket 最大的一点 ,就在于传输协议的不同

网上就张很神奇的七层协议图

图片来自此博客

七层协议

Socket是传输控制层协议 -> 这个靠近中间,不注重数据进行,负责数据传输,速度较快,功能较少

WebSocket是应用层协议-> 应用层靠近用户,然后功能多,所以速度较慢,反向代理,负载均衡,这些都是在这个基础进行

关于 WebSocketSocket 这里我就先讲到这里,

下面是代码实际操作
本篇代码思路来自
C#版Websocket实例 作者:雨落忧伤
下面我就献丑了

后端 NetCore 3.1
前端 Html页面
环境 Windows10
测试浏览器 谷歌
借助工具 nssm ,VS2019

   /// <summary>
    /// Send 发送
    /// </summary>
    public class SocketSend
    {
        private delegate int Weekly(WebSocketServer socket, List<IWebSocketConnection> allSockets,
          string Markmessage,
          int Marknum,
          string ConnectsocketnotificationSection = "已连接",
          string ConnectsocketCloseSection = "连接已关闭",
          string ReturnMesSection = "数据已更新!"

          );
        private static int Marknum = 0;
        private static string Markmessage = "";

        public void Run()
        {
            var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
            var configurationRoot = builder.Build();
            var ipaddresSection = configurationRoot.GetSection("ipaddres").Value;
            var sockettypeSection = configurationRoot.GetSection("sockettype").Value;
            var ipportSection = configurationRoot.GetSection("ipport").Value;
            var ConnectsocketnotificationSection = configurationRoot.GetSection("Connectsocketnotification").Value;
            var ConnectsocketCloseSection = configurationRoot.GetSection("ConnectsocketCloseSection").Value;
            var ReturnMesSection = configurationRoot.GetSection("ReturnMes").Value;
            FleckLog.Level = LogLevel.Debug;
            var allSockets = new List<IWebSocketConnection>();
            var server = new WebSocketServer($"{sockettypeSection }://{ipaddresSection}:{ ipportSection}");
            try
            {
                Weekly weekly = new Weekly(SendMes);
                weekly.Invoke(server, allSockets, Markmessage, Marknum, ConnectsocketnotificationSection, ConnectsocketCloseSection, ReturnMesSection);

            }
            catch (Exception ex)
            {

                Console.WriteLine($"错误:  { ex.Message}");
            }
            var IsExit = Console.ReadLine();
            if (!string.IsNullOrEmpty(IsExit))
            {
                Console.WriteLine("是否关闭程序(Y/N)");
                while (true)
                {
                    IsExit = Console.ReadLine();
                    if (IsExit != "N")
                    {
                        return;
                    }
                }

            }
        }


        /// <summary>
        /// Seed
        /// </summary>
        /// <param name="webSocket"></param>
        /// <param name="allSockets"></param>
        /// <param name="Markmessage"></param>
        /// <param name="Marknum"></param>
        /// <param name="ConnectsocketnotificationSection"></param>
        /// <param name="ConnectsocketCloseSection"></param>
        /// <param name="ReturnMesSection"></param>
        /// <returns></returns>
        private int SendMes(WebSocketServer webSocket, List<IWebSocketConnection> allSockets,
              string Markmessage,
              int Marknum,
              string ConnectsocketnotificationSection = "",
              string ConnectsocketCloseSection = "",
              string ReturnMesSection = ""
              )
        {
            webSocket.Start(socket =>
            {
                socket.OnOpen = () =>
                {
                    Console.WriteLine(ConnectsocketnotificationSection);
                    allSockets.Add(socket);
                };
                socket.OnClose = () =>
                {
                    Console.WriteLine(ConnectsocketCloseSection);
                    allSockets.Remove(socket);

                };
                socket.OnMessage = message =>
                {
                    Markmessage = message;
                    Console.WriteLine(Markmessage);
                    //message 然后开启查询
                    allSockets.ToList().ForEach(s => s.Send($"Echo: {message}"));

                };
            });
            while (true)
            {
                Thread.Sleep(100);
                if (Markmessage == "OK")
                {
                    //对返回值进行分析
                    Marknum = ReceiveMes();
                    //  Console.WriteLine("接收num" + Marknum);
                    if (Marknum == 200)
                    {
                        allSockets.ToList().ForEach(s => s.Send(string.IsNullOrEmpty(ReturnMesSection.ToString()) ? "data Upload!" : ReturnMesSection.ToString()));
                        Console.WriteLine($"收到消息=>{Markmessage} 返回前段消息=>{ReturnMesSection.ToString()}");
                        Markmessage = "";
                    }
                    else
                    {
                        allSockets.ToList().ForEach(s => s.Send(Marknum.ToString()));
                    }
                }
                Console.WriteLine($"监听前端消息=>  {Markmessage}");
            }
        }


        /// <summary>
        /// 接收消息 返回 200成功, 500 表示失败
        /// </summary>
        /// <returns></returns>
        private int ReceiveMes()
        {
            try
            {
               
                //数据库查询
                //查到修改 则跳出循序
                var num = 0;
                while (true)
                {
                    Thread.Sleep(100); //每0.1秒查询一次
                    num++;
                    Console.WriteLine($"执行数据库查询第{num.ToString()}次");
                    if (num > 12)
                    {

                        break;  //跳出数据库查询
                    }
                }
                //表示查询到了数据,返回
                Console.WriteLine($"查询数据成功,正在进行返回数据操作");
                return 200;
            }
            catch (Exception ex)
            {
                //记录Log
                return 500;
            }
        } 

使用nssm把生成的exe创建成服务 Windows服务方式运行控制台程序


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <title>websocket client</title>
    <script type="text/javascript">
        var start = function () {
            var inc = document.getElementById('incomming');
            var wsImpl = window.WebSocket || window.MozWebSocket;
            var form = document.getElementById('sendForm');
            var input = document.getElementById('sendText');

            inc.innerHTML += "connecting to server ..<br/>";

            // create a new websocket and connect
            window.ws = new wsImpl('ws://192.168.1.107:50000');

            // when data is comming from the server, this metod is called
            ws.onmessage = function (evt) {
                inc.innerHTML += evt.data + '<br/>';
            };

            // when the connection is established, this method is called
            ws.onopen = function () {
                inc.innerHTML += '.. connection open<br/>';
            };

            // when the connection is closed, this method is called
            ws.onclose = function () {
                inc.innerHTML += '.. connection closed<br/>';
            }

            form.addEventListener('submit', function (e) {
                e.preventDefault();
                var val = input.value;
                ws.send(val);
                input.value = "";
            });

        }
        window.onload = start;
    </script>
</head>
<body>
    <form id="sendForm">
        <input id="sendText" placeholder="Text to send" />
    </form>
    <pre id="incomming"></pre>
</body>
</html>

这就是将控制台注入成服务,不过我在这样做的时候,有个问题,就是在使用控制台的时候,能打印出了console,但是注入了服务之后,他就不会有黑窗口了
所以,这里你想每一步操作都发送到前端也可以,或者记录log,但是我这里觉得,还是把每一步操作返回前端,出现错误就log记录,好了,本次文章就写在了这里(认真写文章,真的耗时间)
所以觉得帮到你了,或者我引用其他博主的文章,系列您能都能点个赞,没有他们,也不会有我这篇文章 _
有些问题,我可能没有考虑到,有好的优化方案也请能提出,并附上您的Code

Demo地址
Github: https://github.com/whatarey/WebSocket/tree/master
码云: https://gitee.com/Whatarey/WebSocket

文章首发地址 博客园,如果觉得排版不好就点击原文看吧


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM