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處理機制

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM