版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tony19950725/article/details/78931080
Netty4.x下使用HTTP与WebSocket通讯协议
由于公司需求,需要将Netty框架使用的通讯协议由HTTP转成WebSocket协议。由于初学Netty忙了一天,做了一下总结。首先介绍下两者:
HTTP协议
基于传统HTTP协议建立起的连接,大多数使用轮询的方式即客户端每隔1s向服务器端发送请求,服务器端接收到请求将数据返回给客户端。属于半双工通信,HTTP协议中的Header非常冗长,因此会占用很多的带宽和服务器资源。为弥补HTTP请求难以满足频繁请求,占用资源过多的不足,HTML5推出了WebSocket通信协议。
WebSocket协议
WebSocket属于全双工通信协议,即客户端与服务器端建立起链接之后随时可相互通讯传递数据。 在WebSocket API中,浏览器和服务器只需要一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,两者就可以直接互相传送数据了。无消息头,Cookie和消息验证,无安开销,服务器端可以主动传数据给客户端,不需要客户端轮询。WebSocket基于TCP双向全双工协议,即在同一时刻,即可以发送消息,也可以接收消息,相比于HTTP协议,是一个性能上的提升。
二者异同
WebSocket 协议与HTTP协议同处于OSI模型的最高层(应用层),通过TCP/IP协议三次握手与浏览器建立起链接。WebSocket使用HTTPS建立起链接,二者不同之处在于连接之后的数据传输方式。
Netty使用流程
WebSocket的初始化流程
名称 | 职责 |
---|---|
HttpServerCodec | Http编码器。 |
HttpObjectAggregator | Http消息聚合。 |
ChunkedWriteHandler | 大数据处理,主要针对SSL加密解密。 |
HttpRequestHandler | 用户自定义处理ws请求。 |
WebSocketServerProtocolHandler | 处理除TextWebSocketFrame以外的消息事件。所有规定的WebSocket帧类型。 |
TextWebSocketFrameHandler | 用户自定义处理TextWebSocketFrame的消息事件。 |
WebSocketServerCompressionHandler | WebSocket数据压缩 |
Netty同时实现WebSocket与HTTP通讯协议
public class Netty4SocketServer {
private static ServerBootstrap serverBootstrap;
private static EventLoopGroup bossGroup;
private static EventLoopGroup workerGroup;
public void start() throws Exception {
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
try {
serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline.addLast(new HttpServerCodec());
socketChannel.pipeline.addLast(new HttpObjectAggregator(65536));
socketChannel.pipeline.addLast(new ChunkedWriteHandler());
socketChannel.pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
socketChannel.pipeline.addLast(new Netty4MessageHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 1024)
// 等待关闭事件
cf.channel().closeFuture().sync();
//阻塞处理,等待服务端链路关闭之后main函数才退出
} finally {
// 释放资源
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static class Netty4MessageHandler extends SimpleChannelInboundHandler{
@Override
public void messageReceived(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof FullHttpRequest) {//如果是HTTP请求,进行HTTP操作
handleHttpRequest(ctx, (FullHttpRequest) msg);
} else if (msg instanceof WebSocketFrame) {//如果是Websocket请求,则进行websocket操作
handleWebSocketFrame(ctx, (WebSocketFrame) msg);
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
//处理HTTP的代码
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
HttpMethod method=req.method();
String uri=req.uri();
diapathcer(method,uri);
}
private void diapathcer(HttpMethod method,String uri){
if(method==HttpMethod.GET&&"/login".equals(uri)){
//....处理
}else if(method==HttpMethod.POST&&"/register".equals(uri)){
//...处理
}
}
//处理Websocket的代码
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
}