中使用signalr_Asp.Net Core学习笔记:(三)使用SignalR实时通信框架开发聊天室

SignalR牛刀小试

在MVP杨老师的博客里看到这么个东西,我还以为是NetCore3才推出的新玩意,原来是已经有很多年的历史了,那看来还是比较成熟的一个技术了。

简介

SignalR是一个.NET Core/.NET Framework的开源实时框架,SignalR的可使用Web Socket, Server Sent Events 和 Long Polling作为底层传输方式。
SignalR基于这三种技术构建,抽象于它们之上,它让你更好的关注业务问题而不是底层传输技术问题。

以上介绍来自博客,SignalR分为客户端和服务端,服务端运行在AspNetCore上,客户端支持前端、桌面端和移动端,我去查了一下,连Flutter也有相应的支持库。

几个概念

回落机制

SignalR支持三种底层传输技术,根据客户端的兼容性可以自动协商传输类型。如图

5ed68c79f1650c2b567155ea539328ac.png

Web Socket是最好的最有效的传输方式,如果浏览器或Web服务器不支持它的话,就会降级使用SSE,实在不行就用Long Polling。

RPC

不用解释太多,Remote Procedure Call,SignalR采用RPC范式来进行服务端和客户端之间的通信。

Hub

Hub是SignalR的一个组件,运行在服务端,它是一个通信用的组件, Hub使用RPC接受从客户端发来的消息,也能把消息发送给客户端 。

99b7b95e05a4e1f8c48d8b10e2048aab.png

关于横向扩展

SignalR针对多种底层通信方式有了 Sticky Sessions (粘性会话) 这种解决方案,可以保证一个客户端在一次会话中的请求都分配给同一个服务器,具体以后需要的时候再研究。

开始使用

我要做的是一个聊天室,所以只需要写一个简单的服务就可以了。

首先要创建AspNetCore项目,注册SignalR服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddSignalR();
}

创建ChatService类:

public class ChatService
{
    private readonly List<ChatMessage> _messages;
    private readonly IHubContext<ChatHub> _context;
    public List<ChatMessage> Messages { get => _messages; }
    public ChatService(IHubContext<ChatHub> context)
    {
        _context = context;
        _messages = new List<ChatMessage>();
    }
}

消息实体类:

public class ChatMessage
{
    public string UserName { get; set; }
    public string Content { get; set; }
    public DateTime SendedTime { get; set; }
    public string ClientName { get; set; }
}

关键的来了,编写Hub:

使用SendAsync可以进行远程调用

public class ChatHub : Hub {
    private readonly ChatService _chatService;
    public ChatHub(ChatService chatService) {
        _chatService = chatService;
    }
    public async Task GetMessages(string connectionId) {
        var data = _chatService.Messages;
        await Clients.Client(connectionId).
            SendAsync("GetMessages", data);
    }
    public async Task SendMessage(string userName, string content, string clientName) {
        var msg = new Models.ChatMessage {
            UserName = userName,
            Content = content,
            SendedTime = DateTime.Now,
            ClientName = clientName
        };
        _chatService.Messages.Add(msg);
        await Clients.All.SendAsync("SendMessage", msg);
    }
    public override Task OnConnectedAsync() {
        GetMessages(Context.ConnectionId);
        return base.OnConnectedAsync();
    }
}

注册依赖注入和中间件

依赖注入

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddSignalR();
    services.AddSingleton<CountService>();
    services.AddSingleton<ChatService>();
}

中间件

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseStaticFiles();
    app.UseRouting();
    app.UseEndpoints(endpoints =>{
        endpoints.MapControllers();
        endpoints.MapHub<ChatHub>("/chat");
    });
}

客户端

为了方便我就用网页来做。

首先写个简单的聊天界面布局,这里就不贴代码了没啥技术含量,效果大概这样:

e5e856fdcd288ff2f0370733f67fe910.png

首先要安装signalr.js,通过npm安装即可。

然后需要编写js:

function setupConnection() {
    connection = new signalR.HubConnectionBuilder()
        .withUrl("/chat")
        .build();

    connection.on("SendMessage", message => {
        console.log(message);
        addMsg(message.userName, message.sendedTimeStr, message.content, message.clientName);
    });

    connection.on("GetMessages", data => {
        console.log(data);
        for (var i = 0; i < data.length; i++) {
            let message = data[i];
            addMsg(message.userName, message.sendedTimeStr, message.content, message.clientName);
        }
    });

    connection.on("Finished", () => {
        connection.stop();
        console.log("finished.")
    });

    connection.start()
        .catch(err => console.error(err.toString()));
}

通过以下代码可以远程调用服务器的方法:

connection.invoke("SendMessage", username, content, '网页客户端');

然后就可以打开多个浏览器测试了。 这是我在手机上的截图

ecc4a2b11048eeb5f08be6e7192a1daf.png

PS:为了把这个部署到服务器,我还买了个新的阿里云服务器。。

参考资料

  • 杨老师博客:https://www.cnblogs.com/cgzl/p/9515516.html
  • https://juejin.im/post/5c1c7b9c6fb9a049d23606a8
  • AspNetCore应用部署:https://article.itxueyuan.com/dX28oy
  • 启动配置:https://www.cnblogs.com/Hai--D/p/5842842.html

欢迎交流

交流问题请在微信公众号后台留言,每一条信息我都会回复哈~

  • 微信公众号:画星星高手
  • 打代码直播间:https://live.bilibili.com/11883038
  • 知乎:https://www.zhihu.com/people/dealiaxy
  • 专栏:https://zhuanlan.zhihu.com/deali
  • 简书:https://www.jianshu.com/u/965b95853b9f
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值