Signalr 实现心跳包
Posted 风过四季天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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(); } } }; } } }
上面的代码包括四个类:
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" /> <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>: \' + 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>
参考:http://www.cnblogs.com/humble/p/3856357.html
以上是关于Signalr 实现心跳包的主要内容,如果未能解决你的问题,请参考以下文章