工作上遇到一个推送消息的功能的实现。本着面向百度编程的思想。网上百度了一大堆。主要的实现方式是原生的websocket,和signalr。

这里简单的介绍一下signalr,signalr 封装了websocket、foreverframe、serversentevents、longpolling四种主要的传输协议。兼容性比较好,websocket 是有要求的,iis服务需要系统是win8或者 server 2012 以上。下面开始撸代码。

1.首先建立一个项目。

2.通过包管理工具,引入signalr 

3.引入之后,需要手动添加两个类。

pushhub 集线器类,singlarl类的主要操作都由这个类实现。

 1     public class pushhub : hub
 2     {
 3         /// <summary>
 4         /// 第一次连接
 5         /// </summary>
 6         /// <returns></returns>
 7         public override task onconnected()
 8         {
 9             return base.onconnected();
10         }
11 
12         /// <summary>
13         /// 断开连接
14         /// </summary>
15         /// <param name="stopcalled"></param>
16         /// <returns></returns>
17         public override task ondisconnected(bool stopcalled)
18         {
19             string user = connectmanager.getusername(context.connectionid);
20             connectmanager.removeuser(user);
21             show(string.format("{0}退出", user));
22 
23             return base.ondisconnected(stopcalled);
24         }
25 
26         /// <summary>
27         /// 获取当前的用户标识
28         /// </summary>
29         /// <returns></returns>
30         private string getuserid()
31         {
32             return context.querystring["userid"];
33         }
34 
35         /// <summary>
36         /// 发送消息
37         /// </summary>
38         /// <param name="content"></param>
39         /// <param name="receiveuser"></param>
40         public void show(string content,string receiveuser="")
41         {
42             string user = connectmanager.getusername(context.connectionid);
43             if (string.isnullorempty(receiveuser))
44             {
45                 clients.all.show(content);
46             }
47             else {
48                 clients.client(connectmanager.getuserconnect(receiveuser)).show(string.format("{0}发消息:{1}",user, content));
49             }
50             
51         }
52 
53         /// <summary>
54         /// 登录操作
55         /// </summary>
56         /// <param name="user"></param>
57         public void login(string user)
58         {
59 
60             connectmanager.onlineinit(user, context.connectionid);
61             show(string.format("{0}:登录成功", user));
62         }
63 
64     }

 

4.startup类

 

 

    public class startup
    {
        public void configuration(iappbuilder app)
        {
            app.mapsignalr(); //声明注册集线器映射
        }
    }

 

 

5.连接管理类

 1     /// <summary>
 2     /// 连接管理类
 3     /// </summary>
 4     public class connectmanager
 5     {
 6         /// <summary>
 7         /// 连接记录池
 8         /// </summary>
 9         private readonly static concurrentdictionary<string, string> _connectpool = new concurrentdictionary<string, string>();
10 
11         /// <summary>
12         /// 添加用户
13         /// </summary>
14         /// <param name="userkey"></param>
15         /// <param name="connection"></param>
16         public static void adduser(string userkey, string connection)
17         {
18             _connectpool[userkey] = connection;
19         }
20 
21         /// <summary>
22         /// 删除用户
23         /// </summary>
24         /// <param name="userkey"></param>
25         public static void removeuser(string userkey)
26         {
27             string connection = null;
28             _connectpool.tryremove(userkey, out connection);
29         }
30 
31         /// <summary>
32         /// 是否存在连接(是否在线)
33         /// </summary>
34         /// <param name="receiverid"></param>
35         /// <returns></returns>
36         public static bool isonline(string receiverid)
37         {
38             return _connectpool.keys.contains(receiverid);
39         }
40 
41         /// <summary>
42         /// 推送消息给个人
43         /// </summary>
44         /// <param name="receiveid"></param>
45         /// <param name="msg"></param>
46         public static void pushsinglemessage(string receiveid, string msg)
47         {
48             try
49             {
50                 gethubcontext().clients.client(_connectpool[receiveid]).show(msg);
51             }
52             catch (exception ex)
53             {
54                 var errmsg = ex.message;
55             }
56         }
57 
58         /// <summary>
59         /// 获取推送上下文
60         /// </summary>
61         /// <returns></returns>
62         public static ihubcontext gethubcontext()
63         {
64             return globalhost.connectionmanager.gethubcontext<pushhub>();
65         }
66 
67         /// <summary>
68         /// 上线初始化
69         /// </summary>
70         /// <param name="userid">用户id</param>
71         /// <param name="connectionid">连接id</param>
72         public static void onlineinit(string userid, string connectionid)
73         {
74             adduser(userid, connectionid);
75         }
76 
77         public static string getusername(string value)
78         {
79             return _connectpool.where(a => a.value == value).firstordefault().key;
80         }
81 
82         public static string getuserconnect(string username)
83         {
84             return _connectpool[username];
85         }
86     }

 

6.前台代码

<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <div>
        用户名称:<input type="text" id="user" placeholder="输入用户名" class="input" /><input type="button" id="login" value="登录" class="btn btn-sm btn-info" /><br />
        接收人:<input type="text" id="receiveuser" placeholder="接收人(不填默认群发)" class="input" /><br />
        <input type="text" id="content" placeholder="发送内容" class="input" /> &nbsp;&nbsp;<input type="button" value="发送" class="btn btn-sm btn-info" id="send" />
        <div>
            <h4>接收到的信息:</h4>
            <ul id="datacontainer"></ul>
        </div>
    </div>
    <script src="scripts/jquery-3.3.1.min.js"></script>
    <script src="scripts/jquery.signalr-2.4.1.min.js"></script>
    <script src="signalr/hubs"></script>  ///这个要注意默认就是这样写,不要问为什么。哈哈
    <script language="javascript">
        $(function () {
            var chat = $.connection.pushhub;
            
            console.log(chat);
            //连接服务端集线器,demohub为服务端集线器名称,js上首字母须改为小写(系统默认)
            //定义客户端方法,此客户端方法必须与服务端集线器中的方法名称、参数均一致。
            //实际上是服务端调用了前端的js方法(订阅)
            //若多个参数,服务端也需要一致

            chat.client.show = function (content) {
                var html = '<li>' + htmlencode(content) + "</li>";
                $("#datacontainer").append(html);
            }

            //定义推送
            $.connection.hub.start()
                .done(function () {
                    $("#login").click(function () {
                        chat.server.login($("#user").val());  //将客户端的content内容发送到服务端
                        $("#user").val("");
                    });
                    $("#send").click(function () {
                        chat.server.show($("#content").val(), $("#receiveuser").val());  //将客户端的content内容发送到服务端
                        $("#content").val("");
                    });
                });


        });
        //编码
        function htmlencode(value) {
            var encodedvalue = $('<div />').text(value).html();
            return encodedvalue;
        }
    </script>
</body>

</html>

 

这就是所有的demo的代码

demo代码:https://github.com/chaorending/demo.signalr.git