基于webapi的websocket聊天室(三)
上一篇处理了超长消息的问题。我们的应用到目前为止还是单聊天室,这一篇就要处理的多聊天室的问题。
思路
- 第一个问题,怎么访问不同聊天室
这个可以采用路由参数
来解决。我把路由设计成这样/chat/{room}
。访问不同路径就代表进入不同聊天室。
- 第二个问题,怎么创建不同的聊天室
原来的聊天室是单例注入到主机的。因此,多聊天室就不能使用单例了。
我们可以使用一个聊天室工厂,根据路由参数来创建或返回已有的聊天室。而这个工厂需要保存已有的聊天室,所以聊天室工厂需要是单例的。
多聊天室情况下,每个聊天室有个名字还是有必要的
//WebSocketChatRoom.cs
public string roomName { get; set; }
实现
聊天室工厂
- 工厂类
//ChatRoomFactory.cs
/// <summary>
/// 聊天室工厂
/// </summary>
public class ChatRoomFactory
{
public ConcurrentDictionary<string, WebSocketChatRoom> _rooms;
/// <summary>
/// WebSocketChatRoom工厂
/// </summary>
/// <param name="createDelegate">在注册配置WebSocketChatRoom的构造委托</param>
public ChatRoomFactory(Func<WebSocketChatRoom> createDelegate)
{
CreateDelegate = createDelegate;
_rooms = new ConcurrentDictionary<string, WebSocketChatRoom>();
}
private Func<WebSocketChatRoom> CreateDelegate { get; }
public WebSocketChatRoom GetRoom(string path)
{
if (_rooms.TryGetValue(path ,out WebSocketChatRoom socketroom))
{
return socketroom;
}
else
{
var newRoom = CreateDelegate();
newRoom.roomName = path;
this._rooms.TryAdd(path, newRoom);
return newRoom;
}
}
}
- 注册工厂
//program.cs
//添加聊天室服务(不需要了)
//builder.Services.AddSingleton<WebSocketChatRoom>();
//添加聊天室工厂
builder.Services.AddSingleton<ChatRoomFactory>((provider) =>
{
return new ChatRoomFactory(() =>
{
return new WebSocketChatRoom();
});
});
中间件改造
改造的点有两个
- 使用的服务从
WebSocketChatRoom
改为ChatRoomFactory
- 判断路由参数
//WebSocketChatRoomMiddleware.cs
public class WebSocketChatRoomMiddleware
{
private readonly RequestDelegate _next;
public WebSocketChatRoomMiddleware(RequestDelegate next, Func<ChatRoomFactory> handler)
{
_next = next;
Handler = handler;
}
public Func<ChatRoomFactory> Handler { get; }
public async Task InvokeAsync(HttpContext context)
{
await _next(context);
WebSocket client = await context.WebSockets.AcceptWebSocketAsync();
var room = Handler().GetRoom(context.Request.Path.Value.Trim('/')?.ToString() ?? "defaultRoom");
await room.HandleContext(context, client);
}
}
//WebSocketChatRoomMiddlewareExtensions.cs
public static class WebSocketChatRoomMiddlewareExtensions
{
public static WebApplication UseWebSocketChatRoomMiddleware(this WebApplication builder)
{
//建立websocket分支
builder.MapWhen(c => c.WebSockets.IsWebSocketRequest, appbuilder =>
{
//授权
appbuilder.Use(async (context, next) =>
{
if (context.User.Identity.IsAuthenticated)
await next(context);
else
context.Response.StatusCode = StatusCodes.Status403Forbidden;
})
.Map("/chat", roombranch =>
{
roombranch
.UseMiddleware<WebSocketChatRoomMiddleware>(new Func<ChatRoomFactory>(() =>
{
return roombranch.ApplicationServices.GetRequiredService<ChatRoomFactory>();
}));
});
});
return builder;
}
}
聊天室改造
聊天室基本不用改。这里为了明确不同聊天室,就在加入广播和退出广播中加上聊天室名字吧
//WebSocketChatRoom.cs
//广播游客加入聊天室
CascadeMeaasge(null, $"{roomName}: {visitor.Name}加入聊天室");
...
//广播游客退出
CascadeMeaasge(visitor,$"{roomName}: {visitor.Name}退出聊天室");
测试
这里列出每个游客聊天截图,还是用的ApiPost来测的。
基于webapi的websocket聊天室(三)的更多相关文章
- 基于springboot的websocket聊天室
WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...
- 基于flask的网页聊天室(三)
基于flask的网页聊天室(三) 前言 继续上一次的内容,今天完成了csrf防御的添加,用户头像的存储以及用户的登录状态 具体内容 首先是添加csrf的防御,为整个app添加防御: from flas ...
- 使用.NET Core和Vue搭建WebSocket聊天室
博客地址是:https://qinyuanpei.github.io. WebSocket是HTML5标准中的一部分,从Socket这个字眼我们就可以知道,这是一种网络通信协议.WebSocket是 ...
- Netty之多用户的聊天室(三)
Netty之多用户的聊天室(三) 一.简单说明 笔者有意将Netty做成一个系列的文章,因为笔者并不是一个善于写文章的人,而且笔者学习很多技术一贯的习惯就是敲代码,很多东西敲着敲着就就熟了,然后再进行 ...
- Netty入门(一)之webSocket聊天室
一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...
- 基于flask的网页聊天室(四)
基于flask的网页聊天室(四) 前言 接前天的内容,今天完成了消息的处理 具体内容 上次使用了flask_login做用户登录,但是直接访问login_requare装饰的函数会报401错误,这里可 ...
- 用Java构建一个简单的WebSocket聊天室
前言 首先对于一个简单的聊天室,大家应该都有一定的概念了,这里我们省略用户模块的讲解,而是单纯的先说说聊天室的几个功能:自我对话.好友交流.群聊.离线消息等. 今天我们要做的demo就能帮我们做到这一 ...
- websocket聊天室
目录 websocket方法总结 群聊功能 基于websocket聊天室(版本一) websocket方法总结 # 后端 3个 class ChatConsumer(WebsocketConsumer ...
- WebSocket聊天室demo
根据Socket异步聊天室修改成WebSocket聊天室 WebSocket特别的地方是 握手和消息内容的编码.解码(添加了ServerHelper协助处理) ServerHelper: using ...
- 基于flask的网页聊天室(二)
基于flask的网页聊天室(二) 前言 接上一次的内容继续完善,今天完成的内容不是很多,只是简单的用户注册登录,内容具体如下 具体内容 这次要加入与数据哭交互的操作,所以首先要建立相关表结构,这里使用 ...
随机推荐
- MySQL 数据库操作指南:LIMIT,OFFSET 和 JOIN 的使用
限制结果 您可以通过使用"LIMIT"语句来限制查询返回的记录数量.以下是一个示例,获取您自己的Python服务器中"customers"表中的前5条记录: i ...
- Python 数组和列表:创建、访问、添加和删除数组元素
Python 没有内置支持数组,但可以使用 Python 列表来代替. 数组 本页将向您展示如何使用列表作为数组,但要在 Python 中使用数组,您需要导入一个库,比如 NumPy 库.数组用于在一 ...
- MySQL-ERROR 1701 (42000)
清空具有外键约束的表时报ERROR 1701(42000)的解决 mysql> truncate table events; ERROR 1701 (42000): Cannot truncat ...
- Sample Post
HTML Elements Below is just about everything you'll need to style in the blog. Heading 1 Heading 2 H ...
- 面向开发者的HarmonyOS 3.0 Beta发布
原文:https://mp.weixin.qq.com/s/y0h5CUMbuFchwT7g-AqaBQ,点击链接查看更多技术内容. 2021年10月,我们面向开发者发布了HarmonyOS 3.0 ...
- Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration ':classpath'.
前言 这个错误怎么看呢? 如果你对gradle 不是很了解的话,有一个建议,就是把异常背下来,当然是看这个:ArtifactResolveException哈. 而不是后面的详情. 正文 给我们详情是 ...
- arp 的概念解析
前言 这里基于arp的基础概念,请先看前面那一节. 正文 看图: 和前面一样去解析地址. 以太网目的地址:就是mac地址. 在发送arp包的时候呢,这个mac地址就是全部是1,因为不知道对方地址是啥. ...
- 手机配置IPV6
据可靠消息说今年7月份前大部分系统都得支持ipv6,之前也没当回事,突然说要全切,还得验证ipv6的支持情况. 网上找了一堆,发现都过时了,或者行不通,琢磨了一下把华为android的搞定了(流量模式 ...
- uniapp中实现简易计算器
uniapp中实现简易计算器主要问题:在计算器的实现过程中会遇到小数点计算精度:此计算器是依赖了uni-popup的弹出层插件,可在uniapp官方组件中查找扩展插件popup弹窗层下载,也可直接点击 ...
- python之six模块的用法six.py2 six.py3
import six,sys print(six.PY2) #python2结果为True print(six.PY3) #python3结果为True