简介
在上一篇文章中,咱们应用了 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 种类型,别离是:
BinaryWebSocketFrame
CloseWebSocketFrame
ContinuationWebSocketFrame
PingWebSocketFrame
PongWebSocketFrame
TextWebSocketFrame
其中真正蕴含内容的是 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/
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢送关注我的公众号:「程序那些事」, 懂技术,更懂你!