计算机网络 --- WebSocket协议 和 Signalr

计算机网络 --- WebSocket协议 和 Signalr

  • 什么是WebSocket
  • 什么是Signalr
    • Signalr Example -- SimpleChat

什么是WebSocket

  • HTTP是基于TCP协议的,同一时间里,客户端和服务器只能有一方主动发数据,是半双工通信。
  • 通常,打开某个网页,我们每点击一次网页上的某个选项,前端就会发送一次HTTP请求,网站返回一次HTTP响应。这种由客户端主动请求,服务器响应的方式满足大部分网页的功能场景。但这种情况下,服务器不会主动给客户端发消息。而类似网页游戏这样的场景,是需要客户端和服务器之间互相主动发大量数据的。
  • 因此,我们需要一个基于TCP的新协议,即新的应用层协议WebSocket。
  • 它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种

在这里插入图片描述

  • 其他特点包括:
  • 建立在 TCP 协议之上,服务器端的实现比较容易。
  • 与 HTTP 协议有着良好的兼容性。默认端口也是80和
  • 并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  • 数据格式比较轻量,性能开销小,通信高效。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL
    在这里插入图片描述
  • 使用WebSocket注意事项
  • 资源消耗:WebSocket 连接是持久的,这意味着服务器端需要分配和管理每个连接的资源。如果同时有大量连接存在,可能会对服务器的性能和资源消耗造成压力
  • 安全性考虑:由于 WebSocket 允许服务器端向客户端发送实时数据,因此存在安全风险。如果不正确地实施安全措施,可能会导致跨站点脚本攻击(XSS)和其他安全漏洞
  • 连接状态维护:与传统的 HTTP 请求不同,WebSocket 建立了一个持久的连接,需要维护连接状态。这意味着服务器端需要消耗额外的资源来管理连接、保持连接状态和处理连接断开等情况
  • 防火墙和代理限制:某些网络环境中的防火墙或代理服务器可能会阻止 WebSocket 连接。这可能导致在特定网络配置下,无法建立或保持 WebSocket 连接,从而影响实时通信功能的可用性

什么是Signalr

  • 因为WebSocket是无状态的,如果因为网络问题中断的话, 则重连之后, 服务器会丢失所有客户端的信息. 所以使用原生WebSocket的话, 需要自己在服务器端实现状态管理.
  • SignalR 是一个开源的 Microsoft .NET 库,用于实现实时双向通信功能。它简化了在 Web 应用程序中实现实时功能的开发过程,允许服务器端代码能够主动推送数据到客户端,并支持客户端与服务器之间的实时双向通信。
  • SignalR 支持多种传输协议
  • WebSocket
  • Server-Sent Events(SSE)
  • 长轮询
  • Forever Frame
  • Signalr对于每个链接提供了一个connectionId, 这样可以服务器端可以通过connectionId识别出来客户端, 实现状态管理

SignalR 的主要特点包括:

  • 实时双向通信:SignalR 允许服务器端向客户端实时推送数据,同时也支持客户端向服务器端发送消息,实现双向通信。
  • 广播和组管理:SignalR 提供了广播功能,可以将消息同时发送给多个客户端。它还支持将客户端分组,可以根据需要将消息发送给特定的客户端组。
  • 自动重连和状态管理:SignalR 具有自动重连功能,如果连接中断,它会尝试重新建立连接。同时,它还能够管理客户端和服务器之间的连接状态,包括连接建立、连接断开和错误处理等。
  • 扩展性和可定制性:SignalR 可以在不同的扩展点进行定制,开发人员可以根据需要修改消息传输、身份验证和授权等方面的行为。
  • 总体而言,SignalR 提供了一种简单且强大的方式来实现实时双向通信功能,并且能够与 ASP.NET、ASP.NET Core 和其他 .NET 平台无缝集成。

Signalr Example – SimpleChat

服务器端

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

namespace SignalRServer
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();
//将Hub和Http uri进行绑定
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<ChatHub>("/chathub");
            });
        }
    }

    public class ChatHub : Microsoft.AspNetCore.SignalR.Hub
    {
        public async Task Broadcast(string message)
        {
        //"ReceiveMessage" 是客户端注册的接收消息的回调函数的名字
            await Clients.All.SendAsync("ReceiveMessage", message);
        }
		public async Task SendMessage(string message)
        {
            var connectionId = Context.ConnectionId;
            await Clients.All.SendAsync("ReceiveMessage", connectionId, message);
        }
    }
}
  • 在上述代码中,我们首先在 ConfigureServices 方法中添加了 SignalR 服务。然后,在 Configure 方法中注册了 ChatHub,并将其映射到 /chathub 路由。
  • ChatHub 是一个继承自 Microsoft.AspNetCore.SignalR.Hub 的类,它包含了一个名为 SendMessage 的方法,用于接收客户端发送的消息,并将消息通过 Clients.All.SendAsync 发送给所有连接的客户端。

客户端

from signalrcore.hub_connection_builder import HubConnectionBuilder

# 创建 SignalR 连接
connection = HubConnectionBuilder() \
    .with_url("http://example.com/chathub") \
    .build()

# 定义收到消息时的回调函数
def on_message(message):
    print("Received message:", message)

# 注册消息回调函数
connection.on("ReceiveMessage", on_message)

# 启动连接
connection.start()

# 发送消息, SendMessage 是服务器端Hub里定义的接受消息的方法名
while True:
    message = input("Enter a message to send: ")
    connection.send("SendMessage", message)

# 断开连接
connection.stop()
  • 在这个例子中,我们使用 signalrcore 库创建了一个 SignalR 连接,并指定了服务器的 URL(http://example.com/chathub)。然后,我们定义了一个回调函数 on_message,用于处理接收到的消息。接下来,我们通过调用 connection.on() 注册回调函数,以便在收到消息时触发回调函数。
  • 然后,我们通过调用 connection.start() 启动连接。在连接启动后,我们进入一个循环,等待用户输入要发送的消息,并通过调用 connection.send() 发送消息到服务器.

注意

  • Hub 类是Transient的, 也就是用完一次就会被销毁
  • 不要将状态存储在 Hub 类的属性中。每次调用 Hub 方法时,都会在一个新的 Hub 实例上执行。
  • 不要直接通过依赖注入实例化一个 Hub。可以使用 IHubContext 来从应用程序的其他位置向客户端发送消息。
  • 在调用依赖于 Hub 保持活动状态的异步方法时,请使用 await。例如,如果在没有使用 await 的情况下调用类似 Clients.All.SendAsync(…) 的方法,并且在 SendAsync 完成之前 Hub 方法已经完成,那么该方法可能会失败.

使用 IHubContext 从应用程序的其他位置向客户端发送消息

public class NotificationService
{
    private readonly IHubContext<ChatHub> _hubContext;

    public NotificationService(IHubContext<ChatHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task SendNotificationToAllClients(string message)
    {
        await _hubContext.Clients.All.SendAsync("ReceiveNotification", message);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/565792.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt笔记-解决子控制大小获取不正确(width和height)需要重制窗体后,才能获得正确的值

在Qt中&#xff0c;子控件的宽度和高度在构造后并不准确&#xff0c;而只有在调整窗口大小后才正确&#xff0c;这可能是因为子控件的布局或者约束尚未完全计算和应用。 为了解决这个问题&#xff0c;可以使用QTimer来延迟获取子控件的宽度和高度&#xff0c;以确保在布局和约…

ffmpeg初体验

一&#xff1a;安装 sudo yum install epel-release -y sudo yum update -ysudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpmyum -y install …

数据结构(邓俊辉)学习笔记——向量vector_02_动态空间管理

文章目录 1. 概述2. 静态空间管理缺点3. 动态空间管理3.1 扩容3.1.1 如何实现扩容3.1.2 扩容算法3.1.3 容量递增策略 VS 容量倍增策略3.1.3.1 容量倍增策略分摊分析3.1.3.2 容量递增策略分摊分析3.1.3.3 结果对比 3.2缩容3.2.1 动态缩容算法实现3.2.2 动态缩容算法时间复杂度 4…

Opencv_3_图像对象的创建与赋值

ColorInvert.h 如下&#xff1a; #include <opencv.hpp> using namespace std; #include <opencv.hpp> using namespace cv; using namespace std; class ColorInvert{ public : void mat_creation(); }; ColorInvert.cpp 文件如下&#xff1a; #include &q…

自动驾驶---OpenSpace之Hybrid A*规划算法

1 背景 笔者在上周发布的博客《自动驾驶---低速场景之记忆泊车》中&#xff0c;大体介绍了记忆泊车中的整体方案&#xff0c;其中详细阐述了planning模块的内容&#xff0c;全局规划及局部规划&#xff08;会车&#xff09;等内容&#xff0c;包括使用的算法&#xff0c;但是没…

3D Gaussian Splatting介绍

目录 一、概述二、基础介绍1. 多维高斯分布2. 将3D 高斯投影到2D像素平面3. 球谐函数4. Splatting and α \alpha α blending 三、整体流程四、 伪代码五、评价指标六、实验结果七、reference 一、概述 3D Gaussian Splatting和NeRF一样&#xff0c;主要用于新视图合成。 特…

开源博客项目Blog .NET Core源码学习(17:App.Hosting项目结构分析-5)

本文学习并分析App.Hosting项目中前台页面的作品展示页面和首页页面。 作品展示页面 作品展示页面总体上为上下布局&#xff0c;上方显示导航菜单&#xff0c;下方从左向右显示图片数据&#xff0c;支持放大查看图片和下载图片。整个页面使用了layui中的面包屑导航、弹出层、流…

高通发布电脑CPU,比英特尔Ultra9领先51%

要说2024年最热门的关键词&#xff0c;那肯定非 AI 莫属&#xff0c;当前 AI 已经开始深入各行各业&#xff0c;AI 电视、AI 手机、AI 车机、AI 家电&#xff0c;以及 AI PC ,这些都意味着 AI 将对各个行业带来的新风向和不小的冲击。 2024 年了&#xff0c;PC 处理器还能卷出什…

偏微分方程算法之二阶双曲型方程紧差分方法

目录 一、研究目标 二、理论推导 三、算例实现 一、研究目标 前面我们已经介绍了二阶双曲型方程显式、隐式差分格式&#xff0c;可否像抛物型方程一样&#xff0c;构建更高精度的差分格式。接下来我们介绍紧差分格式。这里继续以非齐次二阶双曲型偏微分方程的初边值问题为研…

【JavaScriptThreejs】判断路径在二维平面上投影的方向顺逆时针

原理分析 可以将路径每个连续的两点向量叉乘相加&#xff0c;根据正负性判断路径顺逆时针性 当我们计算两个向量的叉积时&#xff0c;结果是一个新的向量&#xff0c;其方向垂直于这两个向量所在的平面&#xff0c;并且其大小与这两个向量构成的平行四边形的面积成正比。这个新…

Elasticsearch:崭新的打分机制 - Learning To Rank (LTR)

警告&#xff1a;“学习排名 (Learning To Rank)” 功能处于技术预览版&#xff0c;可能会在未来版本中更改或删除。 Elastic 将努力解决任何问题&#xff0c;但此功能不受官方 GA 功能的支持 SLA 的约束。 注意&#xff1a;此功能是在版本 8.12.0 中引入的&#xff0c;并且仅适…

【云计算】云数据中心网络(七):负载均衡

《云网络》系列&#xff0c;共包含以下文章&#xff1a; 云网络是未来的网络基础设施云网络产品体系概述云数据中心网络&#xff08;一&#xff09;&#xff1a;VPC云数据中心网络&#xff08;二&#xff09;&#xff1a;弹性公网 IP云数据中心网络&#xff08;三&#xff09;…

防火墙如何工作

防火墙是网络安全的重要组成部分&#xff0c;充当受信任的内部网络与外部世界之间的保护屏障。它根据预定的安全规则监视和控制传入和传出的网络流量。您是否知道防火墙的概念可以追溯到 20 世纪 80 年代&#xff0c;当时互联网还处于早期阶段&#xff1f;从那时起&#xff0c;…

SpringBoot项目启动的时候直接退出了?

SpringBoot项目启动的时候直接退出了&#xff1f; 如下图&#xff1a; 在启动SpringBoot项目的时候仅仅用了1.209s&#xff0c;然后直接退出了&#xff0c;也没有出现启动的项目对应的服务器端口号&#xff1f;为什么会这样呢&#xff1f;因为既然有服务器端口号 那么肯定会有…

linux系统是未来_大小写敏感_case_sensitive_编程原生态

修改 py 文件 &#x1f94a; 回忆上次内容 上次尝试了 两个vim 同时打开 同一py文件 vim出现了Error 有各种选择 错误拼写 pront 导致 运行时 出现了NameError 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 错误(Error) 不是 我们 无能的标记 …

k8s pod使用sriov

之前的文章中讲了k8s multus的使用&#xff0c;本章节来讲述下如何使用multus来实现sriov的使用。 一、sriov 简介 SR-IOV在2010年左右由Intel提出&#xff0c;但是随着容器技术的推广&#xff0c;intel官方也给出了SR-IOV技术在容器中使用的开源组件&#xff0c;例如&#…

力扣(leetcode) 407. 接雨水 II 3D接雨水

力扣(leetcode) 407. 接雨水 II 3D接雨水 给你一个 m x n 的矩阵&#xff0c;其中的值均为非负整数&#xff0c;代表二维高度图每个单元的高度&#xff0c;请计算图中形状最多能接多少体积的雨水。 示例 1: 输入: heightMap [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] 输…

Excel vlookup函数的使用教程 和 可能遇到的错误解决方法

使用VLOOKUP示例 被查询的表格 表一 A列B列C列A1aB2bC3c 要匹配的列 表二 F列G列H列ACBDA 要G列匹配字母&#xff0c;H列匹配数字 G 使用公式VLOOKUP(F5,A:D,3,0) 参数说明 F5 是表二 F列第五行的A A:D表是要匹配的数据列表在A到D列&#xff0c;就是表一 &#xff08;注意…

day03-(docker)

文章目录 DockerDocker和虚拟机的差别docker在linux安装配置镜像命令容器命令介绍Docker-容器&#xff08;基本操作&#xff09;docker基本操作&#xff08;数据卷&#xff09;数据卷挂载直接挂载四.Dockerfile自定义镜像五.Docker-Compose 安装修改权限镜像仓库![在这里插入图…

在城市与自然中穿行:探索自然的全新方式,健康、环保、快乐的生活方式

一辆单车&#xff0c;三五好友&#xff0c;骑行穿过城市与大自然。无论是在悠闲的周末打卡城市古建筑&#xff0c;还是选择充满挑战的“川藏线”&#xff0c;无论是在城郊绿道感受清风拂面&#xff0c;还是在洱海湖畔欣赏美好风光……如今&#xff0c;越来越多人加入骑行队伍&a…