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 @ 2017-11-02 11:01  望星辰大海  阅读(13870)  评论(1编辑  收藏  举报