首页 > 其他分享 >基于webapi的websocket聊天室(三)

基于webapi的websocket聊天室(三)

时间:2024-05-12 14:20:22浏览次数:16  
标签:webapi 聊天室 websocket next WebSocketChatRoom context return public

上一篇处理了超长消息的问题。我们的应用到目前为止还是单聊天室,这一篇就要处理的多聊天室的问题。

思路

  • 第一个问题,怎么访问不同聊天室

这个可以采用路由参数来解决。我把路由设计成这样/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来测的。
image

image

image

image

标签:webapi,聊天室,websocket,next,WebSocketChatRoom,context,return,public
From: https://www.cnblogs.com/ggtc/p/18187617

相关文章

  • 基于webapi的websocket聊天室(二)
    上一篇-基于webapi的websocket聊天室(一)消息超传缓冲区的问题在上一篇中我们定义了一个聊天室WebSocketChatRoom。但是每个游客只分配了400个字节的发言缓冲区,大概100字。如果需要发送更多内容呢?难道直接增大缓冲区?这是一个办法。但还有其他办法。多次接受消息可以多次调......
  • SpringBoot3集成WebSocket
    标签:WebSocket,Session,Postman。一、简介WebSocket通过一个TCP连接在客户端和服务器之间建立一个全双工、双向的通信通道,使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据,在WebSocket的API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创......
  • 基于webapi的websocket聊天室
    上一次我已经讲了在webapi主机上面加入websocket中间件。这次就更进一步,搭建一个websocket局域网聊天室。传送门-->webapi添加添加websocket中间件聊天室websocket通信其实和win32api里面的消息循环差不多,只不过一个消息来自操作系统,一个来自网络。但核心都是一个阻塞的while......
  • 实时行情数据源接口websocket接入方法
    ​支持如下产品对接:外汇、国际期货、国内期货、国际金银、数字货币、股指期货、美股、印度股、港股、台股、A股产品代码获取地址:http://39.107.99.235:1008/market/market.php产品代码:比特币btcusdt以太坊ethusdt恒指期货HSI德指期货DAX英镑美元fx_sgbpusd欧......
  • 分享一个使用python调用websocket获取实时行情数据的方法
    这个站点可以获取:外汇、国际期货、国内期货、贵金属、能源、虚拟货币、股指期货、美股、台股、港股、印度股、A股、ETF等以下是Python的连接demo,可以参考下。同时也支持其他后端语言的连接,PHP、Java等。获取品种地址:http://39.107.99.235:1008/market/market.phpimportj......
  • 【转】[C#] WebAPI 防止并发调用二(冥等性)
    来自:阿里的通义灵码使用幂等性设计来防止C#WebAPI方法的并发调用是一种推荐的方法,因为它不会阻塞其他请求,而是确保多次调用同一个操作会产生相同的结果。这里有一个简单的示例,说明如何在WebAPI控制器中实现幂等性的API:usingSystem;usingSystem.Web.Http;usingSystem.Lin......
  • 【转】[C#] WebAPI 防止并发调用一(锁)
    来源:阿里的通义灵码在C#WebAPI中,如果你想要使用锁来防止并发调用,你可以使用System.Threading.Mutex或System.Threading.Lock来实现。但是,这种方法通常不推荐,因为它可能会导致请求阻塞,从而影响整个Web服务的性能。在Web环境中,更好的做法是使用幂等性设计或数据库事务来处理并发......
  • Qt开发websocket服务
     Qt自带的有网络编程模块,需要再pro文件加上 websockets#pro文件QT+=coreguiwebsockets .h#ifndefWIDGET_H#defineWIDGET_H#include<QWidget>#include<QWebSocketServer>#include<QWebSocket>#include<QDebug>QT_BEGIN_NAMESPACEna......
  • 实时股票数据API接口websocket接入方法
    一、使用websocket的协议提升传输速度实时金融股票API接口对于投资者和交易员来说至关重要。通过使用WebSocket接入方法,可以轻松获取实时金融股票API接口的数据并及时做出决策。WebSocket是一种高效的双向通信协议,它允许数据的实时推送,避免了不断的轮询请求。这种接入方法具有多......
  • websocket-sharp:.NET平台上的WebSocket客户端与服务器开源库
    1.简介:websocket-sharp提供WebSocket客户端和服务器库,基于C#开发的,并遵循WebSocket协议规范,使得开发人员能够轻松地在.NET应用程序中实现WebSocket通信。https://github.com/sta/websocket-sharpwebsocket-sharp特色功能有:1、简洁易用的API:提供清晰且直观的API接......