netty系列之:分离websocket处理器
简介
在上一篇文章中,我们使用了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/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
netty系列之:分离websocket处理器的更多相关文章
- netty系列之:使用netty搭建websocket服务器
目录 简介 netty中的websocket websocket的版本 FrameDecoder和FrameEncoder WebSocketServerHandshaker WebSocketFra ...
- Netty系列(四)TCP拆包和粘包
Netty系列(四)TCP拆包和粘包 一.拆包和粘包问题 (1) 一个小的Socket Buffer问题 在基于流的传输里比如 TCP/IP,接收到的数据会先被存储到一个 socket 接收缓冲里.不 ...
- Netty 系列(三)Netty 入门
Netty 系列(三)Netty 入门 Netty 是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠性的网络服务器和客户端程序.更多请参考:Netty Github 和 Netty中文 ...
- 探讨Netty获取并检查Websocket握手请求的两种方式
在使用Netty开发Websocket服务时,通常需要解析来自客户端请求的URL.Headers等等相关内容,并做相关检查或处理.本文将讨论两种实现方法. 方法一:基于HandshakeComplet ...
- intel 系列的PC机处理器是大端的还是小端的?
intel 系列的PC机处理器是大端的还是小端的?由于要安装oracle,需要知道是大端机器还是小端的,你好,现在流行的PC,是微型处理器,也就是所谓的小端处理器. 大端处理器是由若干个微型处理器有机 ...
- Netty 系列目录
Netty 系列目录 二 Netty 源码分析(4.1.20) 1.1 Netty 源码(一)Netty 组件简介 2.1 Netty 源码(一)服务端启动 2.2 Netty 源码(二)客户端启动 ...
- webcat——基于netty的http和websocket框架
代码地址如下:http://www.demodashi.com/demo/12687.html Webcat是一个基于netty的简单.高性能服务端框架,目前提供http和websocket两种协议的 ...
- 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?
[读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...
- 1. 彤哥说netty系列之开篇(有个问卷调查)
你好,我是彤哥,本篇是netty系列的第一篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 本文主要讲述netty系列的整体规划,并调查一下大家喜欢的学习方式. 知识点 ne ...
随机推荐
- QT5学习:分割窗口类的使用
分割窗口在应用程序中经常用到,它可以灵活分布窗口布局,经常用于类似文件资源管理器的窗口设计中,然后抱着这样的想法简单的实现了下 [cpp] view plain copy //main.cpp ...
- 十五:JDBC学习入门
一.JDBC相关概念介绍 1.1.数据库驱动 这里的驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡 ...
- SpringBoot快速入门(必知必会)
是什么?能做什么 SpringBoot必知必会 是什么?能做什么 SpringBoot是一个快速开发脚手架 快速创建独立的.生产级的基于Spring的应用程序 SpringBoot必知必会 快速创建应 ...
- PE分析
1 #include<windows.h> 2 #include<RichEdit.h> 3 #include "resource.h" 4 5 6 7 B ...
- -e $request_filename + nginx内置变量
-e表示只要filename存在,则为真,不管filename是什么类型,当然这里加了!就取反额外的一些-e filename 如果 filename存在,则为真-d filename 如果 file ...
- Java HdAcm1174
空间一般直线的方程是:(x-x0)/a=(y-y0)/b=(z-z0)/c,这是一条过(x0,y0,z0),方向矢量为{a,b,c}的直线.假设已知点的坐标是A(e,f,g),过A点,且与{a,b,c ...
- java 方法参数的执行顺序
java方法的参数的执行顺序是从左到右还是从右到左呢? 写出一下测试程序: 1 import java.util.*; 2 import java.io.*; 3 public class Test ...
- shiro登录源码
//1.获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager Factory<org.apache.shiro.mgt.SecurityManage ...
- uniapp 封装 request 并 配置跨域,( 本地 + 线上 + 封装 )
找到上面这个 文件,不管是用 命令创建 还是 用 HBX 创建,都一样会有这个文件的,然后跟着截图复制粘贴就好了. // 这是配置本地能跨域的,或者你可以直接让后端给你设置请求头,避免了跨域. &qu ...
- (五)羽夏看C语言——结构体与类
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...