简介

在上一篇文章中,咱们应用了netty构建了能够解决websocket协定的服务器,在这个服务器中,咱们构建了特制的handler用来解决HTTP或者websocket申请。

在一个handler中解决两种不同的申请,对于某些有代码洁癖的人可能忍耐不了。那么,有没有可能将一般的HTTP申请和websocket申请应用不同的handler来进行解决呢?答案是必定的。

netty的音讯解决

咱们晓得netty中所有的音讯解决都是通过handler来实现的,为了不便起见,netty提供了一个简略的音讯解决类SimpleChannelInboundHandler,大家通过继承它来重写channelRead0办法即可:

protected abstract void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception;

咱们再看一下SimpleChannelInboundHandler的定义:

public abstract class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter

能够看到SimpleChannelInboundHandler自身是带有泛型I的,而这个I就是咱们要探讨的方向。

如果咱们要应用这个handler来解决所有的音讯,那么能够将I取值为Object。

如果咱们只须要解决String音讯,那么能够这样:

       public class StringHandler extends               SimpleChannelInboundHandler<String> {              @Override           protected void channelRead0(ChannelHandlerContext ctx, String message)                   throws Exception {               System.out.println(message);           }       }

同样的,如果要同时解决HTTP和WebSocket音讯,只须要将I设置为不同的类型即可。

对于WebSocketFrame,咱们有:

public class Server2FrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> 

对于FullHttpRequest,咱们有:

public class Server2HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest> 

解决WebSocketFrame

对于WebSocketFrame音讯,从上一节咱们晓得它有6种类型,别离是:

BinaryWebSocketFrameCloseWebSocketFrameContinuationWebSocketFramePingWebSocketFramePongWebSocketFrameTextWebSocketFrame

其中真正蕴含内容的是TextWebSocketFrame和BinaryWebSocketFrame,这里咱们对TextWebSocketFrame进行专门解决:

    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {        if (frame instanceof TextWebSocketFrame) {            // 将接管到的音讯转换成为大写            String request = ((TextWebSocketFrame) frame).text();            ctx.channel().writeAndFlush(new TextWebSocketFrame(request.toUpperCase(Locale.CHINA)));        } else {            String message = "不反对的Frame类型: " + frame.getClass().getName();            throw new UnsupportedOperationException(message);        }    }

解决HTTP

对于HTTP申请中的FullHttpRequest,咱们就装置失常的HTTP服务申请的解决流程来就行。

这里不做过多论述。

编码和解码器

等等,咱们是不是遗记了什么货色?对,那就是编码和解码器。

在上一节中,咱们应用的是WebSocketServerHandshaker来对websocket音讯进行编码和解码。不过其实是放在咱们自定义的hadler代码外面的,应用起来略显不优雅。

没关系,netty为咱们提供了一个WebSocketServerProtocolHandler类,专门负责websocket的编码和解码问题。

除了解决失常的websocket握手之外,WebSocketServerProtocolHandler类还为咱们解决了Close, Ping, Pong这几种通用的音讯类型。而咱们只须要专一于真正的业务逻辑音讯即可,非常的不便。

对于剩下的Text或者Binary frame数据,会被交由pipline中的下一个handler进行解决。

其中Handshake有两个状态,别离是:

HANDSHAKE_COMPLETE 和 HANDSHAKE_TIMEOUT。

而HandshakeComplete又蕴含了requestUri,requestHeaders和selectedSubprotocol这三个方面的信息。

最初,将WebSocketServerProtocolHandler退出到pipeline中,最终失去:

    public void initChannel(SocketChannel ch) throws Exception {        ChannelPipeline pipeline = ch.pipeline();        pipeline.addLast(new HttpServerCodec());        pipeline.addLast(new HttpObjectAggregator(65536));        pipeline.addLast(new WebSocketServerCompressionHandler());        pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));        pipeline.addLast(new Server2HttpHandler());        pipeline.addLast(new Server2FrameHandler());    }

总结

一个拆散了HTTP申请和webSocket申请的服务器就实现了。简略直观才是一个程序员谋求的世界!

本文的例子能够参考:learn-netty4

本文已收录于 http://www.flydean.com/24-netty-websocket-server2/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

欢送关注我的公众号:「程序那些事」,懂技术,更懂你!