Netty入门: 基于Netty的Websocket长连接

前言:Netty入门系列文章大多参考尚硅谷韩顺平老师的《Netty教程》和《Netty in Action》
中文版,以及 bugstack虫洞栈的netty 4.x系列教程。
长连接:长连接,指在一个连接上可以连续发送多个 数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。

HTTP是不支持长连接的,所以本次我们需要使用到WebSocket。

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket是基于HTTP协议的,下面是HTTP升级到WebSocket的过程示意图。

Netty入门: 基于Netty的Websocket长连接_第1张图片

下面正式开始本章的内容—基于nettywebsocket长连接。

项目结果图

Netty入门: 基于Netty的Websocket长连接_第2张图片

代码实现

服务端

public class MyServer {
 public static void main(String[] args) throws Exception{
 // 负责连接的NioEventLoopGroup线程数为1
 EventLoopGroup bossGroup = new NioEventLoopGroup(1);
 EventLoopGroup wokerGroup = new NioEventLoopGroup();
​
 try{
 ServerBootstrap serverBootstrap = new ServerBootstrap();
 serverBootstrap.group(bossGroup,wokerGroup).channel(NioServerSocketChannel.class)
 // 加入日志
 .handler(new LoggingHandler(LogLevel.INFO))
 // 自定义channel初始化器
 .childHandler(new WebSocketChannelInitializer());
 // 绑定本机的8885端口
 ChannelFuture channelFuture = serverBootstrap.bind(new InetSocketAddress(8885)).sync();
 // 异步回调-关闭事件
 channelFuture.channel().closeFuture().sync();
 }finally {
 bossGroup.shutdownGracefully();
 wokerGroup.shutdownGracefully();
 }
​
 }
}

再看看WebSocketChannelInitializer的代码


/**
 * websocket通道初始化器
 *
 * @author linzhe
 * @date 2021/03/12
 */
public class WebSocketChannelInitializer extends ChannelInitializer {
 @Override
 protected void initChannel(SocketChannel ch) throws Exception {
 ChannelPipeline pipeline = ch.pipeline();
 //websocket协议本身是基于http协议的,所以这边也要使用http解编码器
 pipeline.addLast(new HttpServerCodec());
 //以块的方式来写的处理器
 pipeline.addLast(new ChunkedWriteHandler());
 //netty是基于分段请求的,HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度
 pipeline.addLast(new HttpObjectAggregator(8192));
​
 // 使用websocket协议
 //ws://server:port/context_path
 //参数指的是contex_path
 pipeline.addLast(new WebSocketServerProtocolHandler("/world"));
 //websocket定义了传递数据的中frame类型
 pipeline.addLast(new TextWebSocketFrameHandler())
;
 }
}
ChunkedWriteHandler:一个ChannelHandler,它增加了对异步写入大数据流的支持,既不花费大量内存也不获取OutOfMemoryError。诸如文件传输之类的大数据流需要在ChannelHandler实现中进行复杂的状态管理。 ChunkedWriteHandler管理这些复杂的状态,以便您可以毫无困难地发送大型数据流。

TextWebSocketFrameHandler是我们自定义处理长连接的handler

public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler {
 @Override
 protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
 System.out.println("收到消息:"+msg.text());
 /**
 * writeAndFlush接收的参数类型是Object类型,但是一般我们都是要传入管道中传输数据的类型,比如我们当前的demo
 * 传输的就是TextWebSocketFrame类型的数据
 */
 ctx.channel().writeAndFlush(new TextWebSocketFrame("服务时间:"+ LocalDateTime.now()));
 
 }
​
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
 System.out.println("异常发生");
 ctx.close();
 }
}

前端




 
 WebSocket客户端



服务器输出:

结果

Netty入门: 基于Netty的Websocket长连接_第3张图片

Netty入门: 基于Netty的Websocket长连接_第4张图片
Netty入门: 基于Netty的Websocket长连接_第5张图片

你可能感兴趣的:(netty入门)