SignalR初探

伯和蔼
2023-12-01

一.认识SingalR

1.Http协议是浏览器端主动发请求,服务器不能主动发起请求。可以使用ajax或者原生websocket开发,但是难度大。但是使用SignalR,简化了WebSocket开发。

2.SignalR集线器类(SignalR持久连接)是底层机制。

3.可以实现即时通讯。SignalR有三种传输模式:LongLooping(长轮询)、WebSocket(HTML5的WEB套接字)、Forever Frame(隐藏框架的长请求连接)

二.编写代码

1.前端代码

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>OnLineUser</title>
@*注意这个文件是动态创建的,引入的时候尽量放在最后,还有jq和singalR的引入最好按顺序进行引入否则可能会报错*@
    <script src="~/Scripts/jquery-3.3.1.js">
    </script>
    <script src="~/Scripts/jquery.signalR-2.2.2.js"></script>
    <script src="~/signalr/hubs" type="text/javascript"></script>
</head>
<body>
    <input type="text" id="userName" />
    <input type="button" value="click" id="btnlogin" />
    <script>
        $('#btnlogin').click(function(){
var username=$('#userName').val();
$.connection.onLineUserHub.server.login(username);
});
$.connection.onLineUserHub.client.onOnlineUserStatusChange=function(msg)
{
var str = val == ture ? "在线" : "不在线";
                    alert(key+"的状态是" + str);
}
$.connection.hub,start().done(function(){
alert("开启成功Start");
}).fail(function(){
alert("启动失败");
})
    </script>
</body>
</html>

2.后端Hub(TestHub)代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;
using StackExchange.Redis;
using System.IO;
using System.Text;
namespace SingalRProject
{
public class OnLineUserHub:Hub
{
public async Task Login(string userName)
{
using(ConnectionMultiplexer redis=ConnectionMultiplexer.Connect("localhost:6379"))
{
IDatabase db=readis.GetDatabase();
RedisKey strs="key"+this.ContextConnectionId;
var str=await db.StringGetAsync(strs);
if(str.ToString()==userName)
{
await OnDisConectionted(false);
return;
}
var db.StringSetAsync("key"+UserName,true);
await db.StringSetASync("key_UserName"+this.Context.ConnectionId,userName);
await db.SetAddAsync("key_User",UserName);
RedisValue[]userNames=await db.SetMemberAsync("Key_User");
ReduisKey[]userNamesOnlineKeys=userNames.Select(e=>(RedisKey)("key"+e)).ToArray();
Dictionary<string,bool>data=new Dictionary<strung,bool>();
for(int i=0lu<userNames.Length;i++)
{
data[userNames[i]]=(bool)userStatuses[i];
}
Clients.AllonOnlienUsersStatusChange(data);

}
}
public override async Task OnDisconnected(bool stopCalled)
{
using(ConnectionMultiplexer redis=ConnectionMultiplexer,Connect("localhost:6379"))
{
IDatabase db=redis.GetData();
string userName=await db.StringGetAsync("key"+this,Context.ConnectionId);
await db.StringSetAsync("key"+UserName,false);
}
}
}
}
//升级版
namespace SingalRProject
{
public class OnLineUserHub:HUb
{
private static connStr="localhost:6379"
private Object obj=new Object;
private static ConnectionMultiplexer redis;
private static ConnectionMultiplexer _regist
{
get
{
if(redis==null)
{
lock(obj)
{
if(redis==null||redis.IsConnected)
{
redis=redis.Connect(connStr);
}
return redis;
}
}
}
}
public async Task<IDatabase> Db()
{
return _redis.GetDatabase();
}

}
}

捕获SignalR的异常

public class ExceptoinHubPipelineMoudule:HubPipelineModule
{
protected override void OnIncomingError(ExceptionContext exceptionContext,IHubIncomingInvokerContext invokerContext)
{
//可以把异常计入到日志中
base.OnIncomingError(exceptionContext,invokerContext);
 //exceptionContext.Error就是一个异常对象 可以记录到日志里面  记录到分布式的日志
WriteLog(exceptionContext.Error.Message);
dynamic caller=invokerContext.Hub.Clients.Callser;
//把异常信息传递出去
caller.onServerError(exceptionContext.Error.Message);
}
private static string path=@"XXXXX";
public void WriteLog(string ErrorInfo)
{
using(Stream fs=new FileStream(path,FileMode.OpenOrCreate))
{
byte[]info=Encoding.UTF8.GetBytes(ErrorInfo);
fs.Write(info,0,info.Length);
}
}
}
//接着再Global.asax.cs中进行全局的注册
namespace SignalProhect
{
public class MvcApplication:Syste.Web.HttpApplication
{
proteted void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Route);
//进行全局注册SignalR异常捕获
GlobalHost.HubPipeline.AddModule(new HubException());
}
}
}

接下来进行组的添加和删除,在同一组内可以互相进行通信

public class GroupHub:Hub
{
public void AddGroup(string groupName)
{
Groups.Add(this.Context.ConnectionId,groupName);
Clients.All.Hello();
}
public void SendGroupMsg(string grouName,string msg)
{
Clients.OthersInGroup(grouName).onMessage(msg);
Clients.OthersInGroup(grouName).OnMessage2(msg)
}
}

前端页面

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
    <script src="~/Scripts/jquery-3.3.1.js">
    </script>
    <script src="~/Scripts/jquery.signalR-2.2.2.js"></script>
    <script src="~/signalr/hubs" type="text/javascript"></script>

</head>
<body>
    <div id="msgs">
    消息:
    <ul>
        
    </ul></div>
    <div id="msg">
    组名:<input type="text" id="groupName1"/> 
        <button id="btnAddGroup">加入组</button>
     组名:<input type="text" id="groupName2" />
        消息:<input type="text" id="message" />
        <button id="btnSendMsg">发送消息</button>
    </div>
    <script type="text/javascript">
        $.connection.groupHub.client.onMessage = function (msg) {
            $("<li>收到消息1" + msg + "</li>").appendTo("#msgs");
        }
        $.connection.groupHub.client.onMessage2 = function (msg) {
           $("<li>收到消息1" + msg + "</li>").appendTo("#msgs");
        }
        $.connection.hub.start().done(function () {
            $("<li>启动" + "成功"+ "</li>").appendTo("#msgs");
        }).fail(function () {
            alert("开启失败");
        });
        $('#btnAddGroup').click(function () {
            var groupName = $('#groupName1').val();
            //var message = $('#message').val();
            $.connection.groupHub.server.addGroup(groupName);
        });
        $('#btnSendMsg').click(function () {
            var groupName = $('#groupName2').val();
            var message = $('#message').val();
            $.connection.groupHub.server.sendGroupMsg(groupName, message);
        }).fail(function () {
            alert("调用失败");
        })

    </script>
</body>
</html>

 

 类似资料: