netty中的一个小bug
来源:互联网 发布:mysql数据库读写分离 编辑:程序博客网 时间:2024/04/29 06:46
在读netty的websocket处理的handler部分的代码的时候,发现了一个小bug,不过这个bug不会造成太大的影响,我们来看看WebSocketServerProtocolHandler的decode部分的代码:
@Override protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List<Object> out) throws Exception { if (frame instanceof CloseWebSocketFrame) { //如果是用于关闭 WebSocketServerHandshaker handshaker = getHandshaker(ctx); frame.retain(); handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame); //发送用于关闭的websocket帧 return; } super.decode(ctx, frame, out); }
这里
这里当收到的客户端的帧是用于关闭连接的话,按照websocket协议,需要向客户端返回这个帧,然后关闭底层的socket连接,这里是获取以前用到的用于websocket建立连接的握手对象来处理这个帧的,问题就处在这里,因为其实最后获取这个handshaker对象将会是null的,我们来看看获取这个方法的定义:
static WebSocketServerHandshaker getHandshaker(ChannelHandlerContext ctx) { return ctx.attr(HANDSHAKER_ATTR_KEY).get(); }
那么我们再来看看是什么时候set的吧,他是在WebSocketServerProtocolHandshakeHandler里面设置的,前面已经提到,不同版本的websocket需要对应的握手对象来处理,直接来看看代码吧:
@Override public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpRequest req = (FullHttpRequest) msg; if (req.getMethod() != GET) { //如果不是get请求,那么就出错了 sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN)); return; } //创建爱你websocket进行连接握手的工厂类,因为不同版本的连接握手不太一样 final WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( getWebSocketLocation(ctx.pipeline(), req, websocketPath), subprotocols, allowExtensions); final WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(req); //这里会根据不同的websocket版本来安排不同的握手handler if (handshaker == null) { WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel()); } else { //其实这里在将用于建立连接的http报文发送回去之后,会将前面添加的http部分的handler都移除,然后加上用于decode和encode针对websocket帧的handler final ChannelFuture handshakeFuture = handshaker.handshake(ctx.channel(), req); //这里说白了就是进行握手,向客户端返回用于建立连接的报文 handshakeFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { ctx.fireExceptionCaught(future.cause()); } else { ctx.fireUserEventTriggered( //用于激活握手已经完成的事件,可以让用户的代码收到通知 WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE); } } }); WebSocketServerProtocolHandler.setHandshaker(ctx, handshaker); //记录用到的用于握手的对象 ctx.pipeline().replace(this, "WS403Responder", WebSocketServerProtocolHandler.forbiddenHttpRequestResponder()); //将当前这个handler替换,因为只有刚开始使用http协议进行通信,接下来就没有了 } }
在这里,将从factory中获取的shaker对象保存起来,我们知道么一个handlercontext其实也是一个attributemap对象,那么也就是将这个shaker对象放到了当前的ctx中,
而上面获取shaker的时候,却是在WebSocketServerProtocolHandler的context中获取,那么必然将会获取null,这个异常将会被WebSocketServerProtocolHandler的exceptionCaught方法来处理,而这里正好就是将channel关闭了,因此正好,这个bug也不会出现什么问题。。。
- netty中的一个小bug
- J2ME中的一个小BUG
- Microsoft excel中的一个小BUG
- Emgu安装程序中的一个小bug
- linux 一个小bug
- 发现一个小BUG
- LigerUI 控件中的date一个小BUG处理。
- total commander在64位系统中的一个小"bug"
- 工作中的小bug
- Cg中的一个Bug
- IE7中的一个bug
- ipconntrack中的一个BUG
- 违例中的一个BUG
- NALDecoder中的一个bug
- TEmbeddedwb的一个小bug
- gcc的一个小bug
- CStdioFile的一个小Bug
- gmail的一个小bug
- ARM裸机程序开发19(2440lib.c)
- 配置项版本号规则
- background-position的用法
- Linux内核源码分析方法
- C 中for 循环语句执行顺序之我是汇编
- netty中的一个小bug
- Virtual 关键字,派生类重写父类的方法
- zedboard--嵌入式linux系统移植
- 运营商
- 一致性hash算法 - consistent hashing
- 异常机制总结
- PowerMock - mock静态方法
- OpenCV学习笔记(15)使用OpenGL显示双目视觉三维重构效果 (转)
- 逻辑运算符(&&,| |)