首页 > 代码库 > Signalr 实现心跳包

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

Signalr 实现心跳包