zoukankan      html  css  js  c++  java
  • Signalr 实现心跳包

    项目分析:

      一个实时的IM坐席系统,客户端和坐席使用IM通信,客户端使用android和ios的app,坐席使用web。

      web端可以保留自己的登录状态,但为防止意外情况的发生(如浏览器异常关闭,断网,断电),对坐席的实时在线状态造成影响,我们在后台跑一个服务,实时向每个坐席发送一个心跳包,当坐席的状态是在线,但是又不能接收到服务端的心跳包的时候,认为该坐席已经被异常下线。

    实时通信Signalr

      使用中发现signalr的服务端必须需要 .net frameword4.5及以上版本,对signalr使用了自行托管,使服务端和页面相互独立。

      配置过程:

    控制台部分:
    1. 用VS创建一个名为 "SignalRSelfHost" 的控制台项目
    2. 在程序包管理器控制台,输入如下命令
       Install-Package Microsoft.AspNet.SignalR.SelfHost
    3. 输入如下命令:
       Install-Package Microsoft.Owin.Cors
    4. 控制台代码:

    using Microsoft.AspNet.SignalR;
    using Microsoft.Owin.Cors;
    using Microsoft.Owin.Hosting;
    using Owin;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Timers;
    
    namespace SignalRSelfHost
    {
        class Program
        {
            static void Main(string[] args)
            {
                // This will *ONLY* bind to localhost, if you want to bind to all addresses
                // use http://*:8080 to bind to all addresses. 
                // See http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx 
                // for more information.
                string url = "http://localhost:8080";
                using (WebApp.Start(url))
                {
                    Console.WriteLine("Server running on {0}", url);
                    Console.ReadLine();
                }
            }
        }
        class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.UseCors(CorsOptions.AllowAll);
                app.MapSignalR();
            }
        }
        public class MyHub : Hub
        {
            public static List<User> onlineUsers = new List<User>();
            public void Send(string name, string message)
            {
                Console.WriteLine("client messsage from ["+name+"],message:"+message);
                //Clients.All.addMessage(name, "voip:[" + name+"],message:"+message);
                var user = onlineUsers.Where(u => u.Voip == name).FirstOrDefault();
                Clients.Client(user.ConnectionId).addMessage(user.ConnectionId, "voip:[" + name + "],message:" + message);
            }
    
            public void LoginIn(string voip) {
                var user = onlineUsers.Where(u => u.Voip == voip).FirstOrDefault();
                if (user == null)
                {
                    string connId = Context.ConnectionId;
                    user = new User
                    {
                        Voip = voip,
                        Second = 0,
                        ConnectionId=connId
                    };
                    onlineUsers.Add(user);
                    Console.WriteLine(user.Voip + "上线了");
                    //Console.ReadLine();
                    user.HeartBeatAction += () =>
                    {
                        SendHeartBeat(connId);
                    };
                    user.LogoutAction += () =>
                    {
                        LoginOut(voip);
                    };
                }
                else {
                    user.HeartBeatAction += () =>
                    {
                        SendHeartBeat(user.ConnectionId);
                    };
                    user.LogoutAction += () =>
                    {
                        LoginOut(user.Voip);
                    };
                    Console.WriteLine(user.Voip + "已经在线了");
                    Console.ReadLine();
                }
               
            }
    
            /// <summary>
            /// 发送心跳包
            /// </summary>
            /// <param name="voip"></param>
            private void SendHeartBeat(string connid)
            {
                Clients.Client(connid).recieveHeartBeat(connid);
               // Clients.All.recieveHeartBeat(voip);
            }
    
            /// <summary>
            /// 接收心跳包
            /// </summary>
            /// <param name="id"></param>
            public void RecieveHeartBeat(string connid)
            {
                var user = onlineUsers.Where(u => u.ConnectionId == connid).FirstOrDefault();
                if (user == null) return;
                user.Second = 0;
    
            }
    
            /// <summary>
            /// 用户主动下线
            /// </summary>
            /// <param name="voip"></param>
            public void LoginOut(string voip)
            {
    
                var user = onlineUsers.Where(u => u.Voip == voip).FirstOrDefault();
                Console.WriteLine(user.Voip + " 下线了");
               
                onlineUsers.Remove(user);
                
            }
    
            private void UserLoginOut(string voip)
            {
                LoginOut(voip);
            }
        }
    
        public class User
        {
            public string  Voip { get; set; }
            public int  Second { get; set; }
            public string ConnectionId { get; set; }
    
            private readonly Timer timer;//定时器
            /// <summary>
            /// 间隔秒数
            /// </summary>
            private int During=30;
    
            /// <summary>
            /// 掉线后的操作
            /// </summary>
            public event Action LogoutAction;
    
            /// <summary>
            /// 发送心跳包的动作
            /// </summary>
            public event Action HeartBeatAction;
            public User() {
                Second = 0;
                if (timer == null) {
                    timer = new Timer(1000);
                }
                timer.Start();//计时器启动
                timer.Elapsed += (sender, args) =>
                {
                    Second++;
                    //每5s发送一次心跳包
                    if (Second % 5 == 0) {
                        if (HeartBeatAction != null) {
                            HeartBeatAction();
                        }
                    }
                    if (Second >= During) {
                        timer.Stop();
                        timer.Dispose();
                        //用户30s无心跳包应答,则视为掉线,会抛出事件,然后处理用户掉线动作。
                        if (LogoutAction != null)
                        {
                            LogoutAction();
                        }
                    }
                };
    
                
            }
    
        }
    }
    View Code


    上面的代码包括四个类:

        Program,包含程序的主方法.在这个方法中,类型为Startup的web应用程序启动于指定的URL (http://localhost:8080). 如果需要更加安全一点,可以支持SSL. 请去这里看看How to: Configure a Port with an SSL Certificate

        Startup, 该类含有SignalR服务端的配置(该教程使用的唯一的配置是用来调用UseCors), MapSignalR为所有形式的Hub对象创建了路由规则.

        MyHub,  SignalR的Hub 类是程序要提供给客户端的.

        User,存储当前登录坐席的信息


    js部分:

    1. 创建web项目
    2. 初始化客户端需要的东西
       Install-Package Microsoft.AspNet.SignalR.JS
    3. 创建html页,添加客户端代码:

    <!DOCTYPE html>
    <html>
    <head>
        <title>SignalR Simple Chat</title>
        <style type="text/css">
            .container {
                background-color: #99CCFF;
                border: thick solid #808080;
                padding: 20px;
                margin: 20px;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <!--<input type="hidden" id="displayname" />-->
          <span>please enter your name:</span>  <input type="text" id="displayname" />
            <input type="button" id="btnLogin" value="LoginIn" />&nbsp;&nbsp;
            <input type="button" id="btnLoginOut" value="LoginOut" /><br /><br />
            <input type="text" id="message" />
            <input type="button" id="sendmessage" value="Send" />
           
            <ul id="discussion"></ul>
        </div>
        <!--Script references. -->
        <!--Reference the jQuery library. -->
        <script src="Scripts/jquery-1.6.4.min.js"></script>
        <!--Reference the SignalR library. -->
        <script src="Scripts/jquery.signalR-2.2.1.min.js"></script>
        <!--Reference the autogenerated SignalR hub script. -->
        <script src="http://localhost:8080/signalr/hubs"></script>
        <!--Add script to update the page and send messages.-->
        <script type="text/javascript">
            $(function () {
            //Set the hubs URL for the connection
                $.connection.hub.url = "http://localhost:8080/signalr";
                // Declare a proxy to reference the hub.
                var chat = $.connection.myHub;
    
                // Create a function that the hub can call to broadcast messages.
                chat.client.addMessage = function (name, message) {
                    // Html encode display name and message.
                    var encodedName = $('<div />').text(name).html();
                    var encodedMsg = $('<div />').text(message).html();
                    // Add the message to the page.
                    $('#discussion').append('<li><strong>' + encodedName
                        + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
                };
               
                chat.client.recieveHeartBeat = function (connId) {
                    chat.server.recieveHeartBeat(connId);
                    // chat.server.send(localStorage.LoginvoipAccount, "1");
                    console.log('***************************** connId:' + connId);
                };
                // Start the connection.
                $.connection.hub.start().done(function () {
                    $('#sendmessage').click(function () {
                        // Call the Send method on the hub.
                        chat.server.send($('#displayname').val(), $('#message').val());
                        // Clear text box and reset focus for next comment.
                        $('#message').val('').focus();
                    });
    
                    $('#btnLogin').click(function () {
                        chat.server.loginIn($('#displayname').val());
                    });
    
                    $('#btnLoginOut').click(function () {
                        chat.server.loginOut($('#displayname').val());
                    })
                });
            });
        </script>
    </body>
    </html>
    View Code

    参考:http://www.cnblogs.com/humble/p/3856357.html

  • 相关阅读:
    批量 kill mysql 中运行时间长的sql
    第三方支付过程中session失效问题
    Maven常用命令:
    根据Request获取客户端IP
    MySQL之alter语句用法总结
    转:Redis使用认证密码登录
    Git添加远程库
    输入一个三位数x,它的个位数为a,十位数为b,百位数为c,请把它的各个位数分离出来并输出。
    20161129 计算95除以55,商是多少,余数是多少?(商和余数要求分两行显示)
    20161128 已知小明同学其中考试成绩,数学97.5分,语文94.5分,英语95.5分,求小明同学的三科总成绩(结果保留一位小数)。
  • 原文地址:https://www.cnblogs.com/eye-like/p/6290572.html
Copyright © 2011-2022 走看看