• 使用 SignalR与SSE(Sever sent event)向客户端推送提示信息


    最近有个项目想把c/s的代码转成mvc的,这听起来并不困难。
    如果UI和业务逻辑良好分离了的话,不会花太多的功夫,应该多数的内容都能重复利用。

    但在实际的操作过程中,发现业务逻辑代码和UI提示全是混在一起的,尤其里面有这样的代码很多:

    public class MyLogic
    {
        public int DoPress(string bin)
        {
            if (string.IsNullOrEmpty(bin))
            {
                System.Windows.Forms.MessageBox.Show("数据为空,请登录后使用");
                return -1;
            }
    
            return 0;
        }
    }
    

    这是一段伪代码,不是真实的代码内容。这段代码背后有这样的信息:

    • MyLogic类是底层的代码,有很多系统都在调用它,关系错综复杂
    • 代码内需要有合法性的检验,如果合法性校验失败,那函数会被return,错误信息需要让用户看到

    现在的问题是,这个MessageBox.Show()的内容我怎么才能显示用户这一端来呢?

    首先,b/s的程序,这些代码是运行在服务器端的,原来的MessageBox.Show()不会有任何的效果。

    如果我们修改原先的函数签名,将 数据为空,请登录后使用 这句话传输到浏览器,再用javascript的alert来提示。技术上是可以实现的。

    就像这样:

    public class MyLogic
    {
        public Tuple<int, string> DoPress(string bin)
        {
            if (string.IsNullOrEmpty(bin))
            {
                //System.Windows.Forms.MessageBox.Show("数据为空,请登录后使用");
                return new Tuple<int, string>(-1, "数据为空,请登录后使用");
            }
    
            return new Tuple<int, string>(-1, null);
        }
    }
    

    这个Tuple会被返回出去,最后传输到浏览器。

    然而,这会修改原先的函数签名,所有使用DoPress的函数都要修改,并且,有的地方还是使用反射来调用的,要这样修改,会带来巨大的工作量,

    根据这个具体的情况,我不得不去想如何在有限的时间内来完成这件事。

    问题的核心是:如何不修改函数的签名,并将相关的信息输出到浏览器?

    我首先浮现了第一个解决方案是SSE(Server sent event),它是HTML5里服务器向客户端推送事件的一种方式。很快我写了一个小的demo来进行测试,确实可以用,但是有问题:非常的慢,Server产生了消息之后,最长需要等待4秒才能看到提示消息。

    我google了这个问题,也看到其他人的讨论:https://stackoverflow.com/questions/12297740/server-sent-events-work-but-with-a-massive-time-delay

    但最后这个问题还是没有解决。

    于是我转向了SignalR,很快写了另外的一个demo,这次工作良好,消息瞬时到达。

    那么,之前的项目修改成什么样子呢?

    public class MyLogic
    {
        public int DoPress(string bin)
        {
            if (string.IsNullOrEmpty(bin))
            {
                MessagePushHelper.PushSignalR("数据为空,请登录后使用");
                return -1;
            }
    
            return 0;
        }
    }
    

    可以看到,之前的MessageBox.Show()改成了我自己写的MessagePushHelper.PushSignalR(),其他位置不变,这样应该是最小改动的解决方案了。

    只不过有一点需要注意的是:要注意多个用户同时使用时的情况(你不能对外广播出错消息)

    最后,简单的记录一下步骤:

    若要使用SSE

    • 将输出内容标记为 text/event-stream
    • 输出你想要的内容

    若要使用SignalR

    • nuget包 install-package Microsoft.AspNet.SignalR
    • 创建hub
    • 创建startup类,打上OwinStartup标记
    • 在页面引用 jquery.signalR-2.2.2.min.js和signalr/hubs
    • 启动hub并接收数据

    文中提到的解决方案,可在github上查看:https://github.com/syler/Fun/tree/master/SSE-SignalR

    本文地址:http://www.cnblogs.com/asis/p/signalr-sse.html

    我的博客地址:https://1few.com/SSE-SignalR

  • 相关阅读:
    网络基础、多线程、ftp任务铺垫
    文件上传下载、socketserver(并发)、解读socketserver源码
    模拟ssh、黏包、hashlib模块(MD5)
    面向对象多继承(C3算法)/网络编程
    Slideout吐槽
    HDU 1756 Cupid's Arrow 判断点在多边形的内部
    POJ 1584 A Round Peg in a Ground Hole 判断凸多边形,判断点在凸多边形内
    位运算 找出给定的数中其他数都是两个,有两个是一个的数
    NYOJ 1107 最高的奖励(贪心+优先队列)
    POJ 2653 Pick-up sticks (判断线段相交)
  • 原文地址:https://www.cnblogs.com/asis/p/signalr-sse.html
Copyright © 2020-2023  润新知