百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

SignalR 简化:使用 SimpleR for .NET Core创建高性能WebSocket服务

ccwgpt 2024-10-27 08:48 50 浏览 0 评论

概述:互联网的发展使即时通信技术比以往任何时候都更加重要,尤其是对于物联网 (IoT)。由于智能家居设备和工业传感器等众多设备需要顺利地相互通信,因此快速可靠的通信至关重要。这就是 WebSockets 的用武之地。它们非常适合在物联网设备和服务器之间进行快速的双向聊天,帮助一切保持实时连接和最新状态。什么是 SignalR?SignalR 现在是 ASP.NET Core Framework 的一部分,是使用 .net 创建实时应用程序的事实标准。SignalR 是 ASP.NET Core 套件中的高级框架,旨在生成实时 Web 应用程序。它使用自定义协议抽象了实时通信的复杂性,使开发人员能够更

互联网的发展使即时通信技术比以往任何时候都更加重要,尤其是对于物联网 (IoT)。由于智能家居设备和工业传感器等众多设备需要顺利地相互通信,因此快速可靠的通信至关重要。这就是 WebSockets 的用武之地。它们非常适合在物联网设备和服务器之间进行快速的双向聊天,帮助一切保持实时连接和最新状态。

什么是 SignalR?

SignalR 现在是 ASP.NET Core Framework 的一部分,是使用 .net 创建实时应用程序的事实标准。

SignalR 是 ASP.NET Core 套件中的高级框架,旨在生成实时 Web 应用程序。它使用自定义协议抽象了实时通信的复杂性,使开发人员能够更多地关注应用程序逻辑而不是底层协议。SignalR 的一个关键优势是它支持客户端和服务器之间通信的多种传输,确保应用程序可以在不同环境中保持实时功能。这些运输包括:

  1. WebSockets,用于全双工通信,非常适合需要高频数据交换的场景。
  2. 服务器发送事件 (SSE),允许服务器在单向通信充分的情况下将更新推送到客户端。
  3. 长轮询,一种回退机制,当客户端或服务器环境不支持更高级的通信方法时,可以使用该机制。

通过自动选择最佳可用传输方法,SignalR 可确保在各种设备和网络条件下为 Web 应用程序提供最佳功能和性能。

SignalR 是用于开发实时 Web 应用程序的绝佳框架。但是,它对特定协议和客户端兼容性的依赖可能会引入限制,尤其是在需要直接 WebSocket 通信的情况下。

简单

进入 SimpleR,这是一个基于 ASP.NET Core 的高性能、低开销、纯 WebSocket 服务器库。SimpleR 旨在弥合 SignalR 可能不是最佳选择的差距,它在简单性和灵活性方面大放异彩。它删除了繁重的协议和抽象,转而提供一种简单、高效的方法来实现纯 WebSocket 服务器。这使得它成为需要直接控制 WebSocket 通信、自定义协议实现或使用非 SignalR 客户端(例如,使用具有自己的自定义协议的 IoT 设备时)的项目的理想候选者。

在对 SimpleR 的介绍中,我们将探讨其主要功能,并演示如何与 ASP.NET Core 无缝集成,以实现轻量级高性能 WebSocket 服务器的开发。

设计理念

SimpleR 主要基于 SignalR 构建,建立在 ASP.NET Core 团队所做的出色工作之上。它旨在提供

  1. 通过网络传输实现高性能、低分配抽象,同时与所有 ASP.NET Core 功能完全集成。
  2. 性能和最少的分配优先于易用性。
  3. 与协议无关的方法。

设置环境

在深入了解使用 SimpleR 的细节之前,您需要从基础知识开始——创建一个空的 ASP.NET Core Web 应用程序。这为设置 WebSocket 服务器提供了一个全新的石板。

  1. **打开命令行界面 (CLI):**导航到要创建项目的文件夹。
  2. 创建新的 Web 项目:运行以下命令以生成空的 ASP.NET Core Web 应用程序
dotnet new web -n SimpleThermostat.Server

3. **导航到项目文件夹:**将目录更改为新创建的项目文件夹

cd SimpleThermostat.Server

4. 安装 SimpleR.Server 包:在项目目录下,运行以下命令,将 SimpleR.Server 包添加到项目中。在撰写本文时,SimpleR 仍处于 alpha 阶段。

dotnet add package SimpleR.Server --version 1.0.0-alpha.1

定义协议

让我们从定义客户端和服务器消息开始。为了允许不同类型的消息,我们将使用 System.Text.Json 多态序列化功能。

客户端(在本例中为恒温器)将向服务器发送指标。

[JsonDerivedType(typeof(ThermostatTemperatureMetric), "temperature")]  
public class ThermostatMetric;  
  
public class ThermostatTemperatureMetric : ThermostatMetric  
{  
    public ThermostatTemperatureMetric(float temperature)  
    {  
        Temperature = temperature;  
    }  
  
    public float Temperature { get; }  
}

另一方面,服务器将向恒温器发送命令。

[JsonDerivedType(typeof(SetThermostatModeCommand), "setMode")]  
public class ThermostatCommand;  
  

public class SetThermostatModeCommand : ThermostatCommand  
{  
    public SetThermostatModeCommand(ThermostatMode mode)  
    {  
        Mode = mode;  
    }  
  
    public ThermostatMode Mode { get; }  
}  
  
public enum ThermostatMode  
{  
    Off,  
    Heat,  
    Cool  
}

现在我们已经拥有了协议支持的所有消息,让我们定义如何将它们转换为字节,反之亦然。

SimpleR 的关键点之一是它与协议无关。这意味着它要求用户提供协议定义,以便能够从字节流中构造消息。

在这个演示中,我们不会深入定义我们自己的自定义协议,而是使用 WebSocket 的 EndOfMessage 作为消息的分隔符。

为此,我们需要定义一对读取器和编写器类。

// Since we are using WebSocket's EndOfMessage as a delimiter,  
// need to implement the IDelimitedMessageReader interface  
public class ThermostatMessageReader : IDelimitedMessageReader<ThermostatMetric>  
{  
    public ThermostatMetric ParseMessage(ref ReadOnlySequence<byte> input)  
    {  
        var jsonReader = new Utf8JsonReader(input);  
  
        return JsonSerializer.Deserialize<ThermostatMetric>(ref jsonReader)!;  
    }  
}public class ThermostatMessageWriter : IMessageWriter<ThermostatCommand>  
{  
    public void WriteMessage(ThermostatCommand message, IBufferWriter<byte> output)  
    {  
        var jsonWriter = new Utf8JsonWriter(output);  
        JsonSerializer.Serialize(jsonWriter, message);  
    }  
}

现在我们已经成功定义了自己的消息协议,我们准备继续讨论应用程序逻辑。

调度消息

SimpleR 中的下一个重要主题是消息调度程序。简而言之,消息调度器是一个高级管道,它封装了调度连接消息的逻辑。这是我们应用程序逻辑的初始入口。

public class ThermostatMessageDispatcher : IWebSocketMessageDispatcher<ThermostatMetric, ThermostatCommand>  
{  
    private float _targetTemp = 22;  
      
    public Task OnConnectedAsync(IWebsocketConnectionContext<ThermostatCommand> connection)  
    {  
        return Task.CompletedTask;  
    }  
  
    public Task OnDisconnectedAsync(IWebsocketConnectionContext<ThermostatCommand> connection, Exception? exception)  
    {  
        return Task.CompletedTask;  
    }  
  
    public async Task DispatchMessageAsync(IWebsocketConnectionContext<ThermostatCommand> connection, ThermostatMetric message)  
    {  
        if(message is ThermostatTemperatureMetric temperatureMetric)  
        {  
            // update temperature  
              
            if (temperatureMetric.Temperature < _targetTemp)  
            {  
                // If the temperature is below the target temperature, set the thermostat to heat mode  
                await connection.WriteAsync(new SetThermostatModeCommand(ThermostatMode.Heat));  
            }  
            else if (temperatureMetric.Temperature > _targetTemp)  
            {  
                // If the temperature is above the target temperature, set the thermostat to cool mode  
                await connection.WriteAsync(new SetThermostatModeCommand(ThermostatMode.Cool));  
            }  
            else  
            {  
                // If the temperature is at the target temperature, turn off the thermostat  
                await connection.WriteAsync(new SetThermostatModeCommand(ThermostatMode.Off));  
            }  
        }  
    }  
}

将一切连接在一起

定义消息协议和消息调度程序后,我们就可以在 Program.cs 文件中将其连接在一起。

var builder = WebApplication.CreateBuilder(args);  
  
builder.Services.AddSimpleR();  
  
var app = builder.Build();  
  
app.MapSimpleR<ThermostatMetric, ThermostatCommand>("thermostat/{deviceId}", b =>  
{  
    b.UseDispatcher<ThermostatMessageDispatcher>()  
        .UseEndOfMessageDelimitedProtocol(  
            MessageProtocol.From(new ThermostatMessageReader(), new ThermostatMessageWriter()));  
});  
  
app.Run();

就这么简单!

您可以在此处找到服务器的源代码以及一个简单的客户端。

要探索 SimpleR 的所有功能,请查看 Github 存储库中的文档。如果您发现它有用,请不要忘记为存储库加星标。

当我们结束对 SimpleR 的研究时,很明显,对于那些需要直接控制 ASP.NET Core 中的 WebSocket 通信的人来说,这个库是一个不错的选择。展望未来,我们有令人兴奋的计划来使 SimpleR 变得更好。我们将添加现成的协议,使构建应用程序更容易,并包括用于广泛使用的标准(如 OCPP)的特殊软件包。

相关推荐

RACI矩阵:项目管理中的角色与责任分配利器

作者:赵小燕RACI矩阵RACI矩阵是项目管理中的一种重要工具,旨在明确团队在各个任务中的角色和职责。通过将每个角色划分为负责人、最终责任人、咨询人和知情人四种类型,RACI矩阵确保每个人都清楚自己...

在弱矩阵组织中,如何做好项目管理工作?「慕哲制图」

慕哲出品必属精品系列在弱矩阵组织中,如何做好项目管理工作?【慕哲制图】-------------------------------慕哲制图系列0:一图掌握项目、项目集、项目组合、P2、商业分析和NP...

Scrum模式:每日站会(Daily Scrum)

定义每日站会(DailyScrum)是一个Scrum团队在进行Sprint期间的日常会议。这个会议的主要目的是为了应对Sprint计划中的不断变化,确保团队能够有效应对挑战并达成Sprint目标。为...

大家都在谈论的敏捷开发&amp;Scrum,到底是什么?

敏捷开发作为一种开发模式,近年来深受研发团队欢迎,与瀑布式开发相比,敏捷开发更轻量,灵活性更高,在当下多变环境下,越来越多团队选择敏捷开发。什么是敏捷?敏捷是一种在不确定和变化的环境中,通过创造和响应...

敏捷与Scrum是什么?(scrum敏捷开发是什么)

敏捷是一种思维模式和哲学,它描述了敏捷宣言中的一系列原则。另一方面,Scrum是一个框架,规定了实现这种思维方式的角色,事件,工件和规则/指南。换句话说,敏捷是思维方式,Scrum是规定实施敏捷哲学的...

敏捷项目管理与敏捷:Scrum流程图一览

敏捷开发中的Scrum流程通常可以用一个简单的流程图来表示,以便更清晰地展示Scrum框架的各个阶段和活动。以下是一个常见的Scrum流程图示例:这个流程图涵盖了Scrum框架的主要阶段和活动,其中包...

一张图掌握项目生命周期模型及Scrum框架

Mockito 的最佳实践(mock方法)

记得以前面试的时候,面试官问我,平常开发过程中自己会不会测试?我回答当然会呀,自己写的代码怎么不测呢。现在想想我好像误会他的意思了,他应该是想问我关于单元测试,集成测试以及背后相关的知识,然而当时说到...

EffectiveJava-5-枚举和注解(java枚举的作用与好处)

用enum代替int常量1.int枚举:引入枚举前,一般是声明一组具名的int常量,每个常量代表一个类型成员,这种方法叫做int枚举模式。int枚举模式是类型不安全的,例如下面两组常量:性别和动物种...

Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!

Maven简介Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”。Maven是一个跨平台的项目管理工具。主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。仔...

Java单元测试框架PowerMock学习(java单元测试是什么意思)

前言高德的技术大佬在谈论方法论时说到:“复杂的问题要简单化,简单的问题要深入化。”这句话让我感触颇深,这何尝不是一套编写代码的方法——把一个复杂逻辑拆分为许多简单逻辑,然后把每一个简单逻辑进行深入实现...

Spring框架基础知识-第六节内容(Spring高级话题)

Spring高级话题SpringAware基本概念Spring的依赖注入的最大亮点是你所有的Bean对Spring容器的存在是没有意识的。但是在实际的项目中,你的Bean必须要意识到Spring容器...

Java单元测试浅析(JUnit+Mockito)

作者:京东物流秦彪1.什么是单元测试(1)单元测试环节:测试过程按照阶段划分分为:单元测试、集成测试、系统测试、验收测试等。相关含义如下:1)单元测试:针对计算机程序模块进行输出正确性检验工作...

揭秘Java代码背后的质检双侠:JUnit与Mockito!

你有没有发现,现在我们用的手机App、逛的网站,甚至各种智能设备,功能越来越复杂,但用起来却越来越顺畅,很少遇到那种崩溃、卡顿的闹心事儿?这背后可不是程序员一拍脑袋写完代码就完事儿了!他们需要一套严谨...

单元测试框架哪家强?Junit来帮忙!

大家好,在前面的文章中,给大家介绍了以注解和XML的方式分别实现IOC和依赖注入。并且我们定义了一个测试类,通过测试类来获取到了容器中的Bean,具体的测试类定义如下:@Testpublicvoid...

取消回复欢迎 发表评论: