Netty-Websocket 根据URL路由,分发机制的实现

最近在做netty整合websocket,发现网上很多项目都是最简单的demo,单例的一个项目。

然而公司的项目需要接受几个不同功能的ws协议消息,因此最好是用URL来区分,让页面上采用不同的链接方式。

 

网上项目出现地址的方法:

复制代码
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
        // 如果HTTP解码失败,返回HHTP异常
        if(!req.decoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
            
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
            
            return;
        }
        // 构造握手响应返回,本机测试
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory("ws://localhost:8088/websocket", null,
                false);  //注意,这条地址别被误导了,其实这里填写什么都无所谓,WS协议消息的接收不受这里控制
        
        handshaker = wsFactory.newHandshaker(req);
        
        if(handshaker == null) {
            // WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
            
        } else {
            handshaker.handshake(ctx.channel(), req);
        }
        
    }
复制代码

然后,开始看源码,发现ChannelHandlerContext继承的 AttributeMap

然后继续看,AttributeMap有一个方法,attr(),返回Attribut,参数key。而Attrbute中有set()方法。

好了,那么接下来一切都好办了,直接上关键代码。

下面是netty接收到消息处理,第一步首先是http握手,这个没的说。

复制代码
/**
     * 接收客户端发送的消息 channel 通道 Read 读 简而言之就是从通道中读取数据,也就是服务端接收客户端发来的数据。但是这个数据在不进行解码时它是ByteBuf类型的
     */
    @Override
    protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
         // 传统的HTTP接入
        if (msg instanceof FullHttpRequest) {
            handleHttpRequest(ctx, ((FullHttpRequest) msg));
            // WebSocket接入
        } else if (msg instanceof WebSocketFrame) {
            if("anzhuo".equals(ctx.attr(AttributeKey.valueOf("type")).get())){
            handlerWebSocketFrame(ctx, (WebSocketFrame) msg);
            System.out.println(1111);
            }else{
            System.out.println(2323);
            handlerWebSocketFrame2(ctx, (WebSocketFrame) msg);
            }
        }
    }
    
复制代码

然后:

复制代码
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
        // 如果HTTP解码失败,返回HHTP异常
        if (!req.getDecoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
            sendHttpResponse(ctx, req,
                    new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
            return;
        }
        
         HttpMethod method=req.getMethod();
         String uri=req.getUri();
        if(method==HttpMethod.GET&&"/webssss".equals(uri)){
             //....处理    重点在这里,对于URL的不同,给ChannelHandlerContext设置一个Attribut
            ctx.attr(AttributeKey.valueOf("type")).set("anzhuo");
         }else if(method==HttpMethod.GET&&"/websocket".equals(uri)){
             //...处理
             ctx.attr(AttributeKey.valueOf("type")).set("live");
         }

          // 构造握手响应返回,本机测试
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                "ws://localhost:7397/websocket", null, false);
        handshaker = wsFactory.newHandshaker(req);
        if (handshaker == null) {
            WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
        } else {
            handshaker.handshake(ctx.channel(), req);
        }
    }
复制代码

握手成功之后,发送消息时会返回第一段代码,因此判断context的Attribut就可以分发路由了,给不同的handlerWebSocketFrame处理机制

 

posted @   望星辰大海  阅读(13924)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示