问题来源:
前端请求后端动态生成资源的一种解决方案,防止http请求处于waiting态导致的499错误_董厂长的博客-CSDN博客
此问题自己的实现方式是长轮询,但是实际效果不够好。
服务器向客户端发送数据
1、需求:Web聊天;站内通知。
2、传统HTTP:只能客户端主动发送请求。
3、传统方案:长轮询(Long Polling)。缺点是 服务器🍐压力很大
HTML5 中的WebSocket
1、WebSocket基于TCP协议,支持二进制通信,双工通信。(两端可以互相发送)
2、性能和并发能力更强。
3、WebSocket独立于HTTP协议,不过我们一般仍然把WebSocket服务器端部署到Web服务器上,因为可以借助HTTP协议完成初始的握手(可选),并且共享HTTP服务器的端口(主要)。
特别注意:webSocket 和 HTTP 是同一等级的东西,他们都是基于TCP协议的。
http是文本通讯,一般会经历序列化和反序列化,消耗比较高,WebSocekt是二进制,消耗低。
1、ASP.NET Core SignalR(以下简称SignalR),是.NET Core平台下对WebSocket的封装。
2、Hub(集线器),数据交换中心。
需要分别编写服务器端Hub和前端代码。
1、创建Web API项目,创建一个继承自Hub类
这段代码 的 意思:某个客户端连接到HUB,调用此方法,然后广播给所有连接到同一个HUB的客户端
- public class ChatRoomHub:Hub
-
- {
-
- public Task SendPublicMessage(string message)//message是 服务器端接收到客户端的消息
-
- {
-
- string connId = this.Context.ConnectionId;//获取当前链接到HUB的链接字符串ID 不同的链接有对应的id
-
- string msg = $"{connId} {DateTime.Now}:{message}";
-
- return Clients.All.SendAsync("ReceivePublicMessage", msg);
- // 服务器端向客户端发送消息 第一个参数是服务器端的名字
- // Clients是HUB类的一个属性,不要迷惑
-
- }
-
- }
2、在项目里面注册 AddSingnalR 的服务
- builder.Services.AddSignalR()
-
- app.MapControllers()之前
- 调 app.MapHub
(“/Hubs/ChatRoomHub”) - //默认还要启用CORS。
然后在MapControllers中:
解读一下,仍和客户端访问 /MyHub 这个路径的时候,都会交给MyHub class来处理
什么是MapControllers?
MapControllers is used to map any attributes that may exist on the controllers, like, [Route], [HttpGet], etc. From Microsoft: Adds endpoints for controller actions to the Microsoft.AspNetCore.Routing.IEndpointRouteBuilder without specifying any routes. Explain: This says it will map url to controller and action, you need specify your own route
注意还要开启CROS
复习:CORS原理:在服务器的响应报文头中通过access-control-allow-origin告诉浏览器允许跨域访问的域名。
A、在Program.cs的“var app=builder.Build()”这句代码之前注册
- string[] urls = new[] { "http://localhost:3000" };
-
- builder.Services.AddCors(options =>
-
- options.AddDefaultPolicy(builder => builder.WithOrigins(urls)
-
- .AllowAnyMethod().AllowAnyHeader().AllowCredentials()));
B、在Program.cs的app.UseHttpsRedirection()这句代码之前增加一行app.UseCors()
- <template>
-
- <input type="text" v-model="state.userMessage" v-on:keypress="txtMsgOnkeypress"/>
-
- <div><ul>
-
- <li v-for="(msg,index) in state.messages" :key="index">{{msg}}li>
-
- ul>div>
- import { reactive, onMounted } from 'vue';
- import * as signalR from '@microsoft/signalr';
- let connection;
-
- export default {name: 'Login',
- setup() { const state = reactive({ userMessage: "", messages: [] });
-
- const txtMsgOnkeypress = async function (e) {
- if (e.keyCode != 13) return;
- // 看这边 傻逼 开始操作了 这边是发消息给服务端
- await connection.invoke("SendPublicMessage", state.userMessage);
- state.userMessage = "";
- };
-
- onMounted(async function () {
- // 创建了 signalR 的链接!!
- connection = new signalR.HubConnectionBuilder()
- .withUrl('https://localhost:7112/Hubs/ChatRoomHub')//写全路径啊!
- .withAutomaticReconnect().build();//重连机制 非必需
- await connection.start();//启动
- connection.on('ReceivePublicMessage', msg => {
- state.messages.push(msg); //看!接收到服务器端端消息的时候,才执行哦!
- });
- });
-
- return { state, txtMsgOnkeypress };
- },
- }
今天这个b学习先到此为止,关于更多的关于signalR的细节,等过两天再开一贴
前后端一起开放真累啊🤔