18.Netty-WebSocket编码实战

基础组件:3.Netty全局入口Bootstrap · 5.Netty的EventLoop · 6.Netty的ChannelPipeline · 7.Netty的ChannelHandler与Context

1. 启动类

public static void main(String[] args) throws InterruptedException {
    //主从线程池
    // 主接收客户端连接
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();

    try {
        //Netty启动类 装线程进去
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup)
                //设置Nio的双向通道
                .channel(NioServerSocketChannel.class)
                //workergroup的处理器
                .childHandler(new WSServerInitializer());

        //绑定端口,[同步]等待成功
        ChannelFuture channelFuture = bootstrap.bind(10086).sync();
        //监听关闭的Channel
        channelFuture.channel().closeFuture().sync();

    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

2. 初始化器


public class WSServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        //通过Channel获取管道
        ChannelPipeline pipeline = channel.pipeline();
        //通过管道 添加 Handler处理器 http的编解码处理器
        // websocket 基于http
        pipeline.addLast("HttpServerCodec", new HttpServerCodec());

        //添加对大数据流的支持
        pipeline.addLast(new ChunkedWriteHandler());

        // 对HttpMessage进行聚合,聚合为FullHttpResponse或FullHttpRequest
        // 几乎在netty的编程中,都会使用它
        pipeline.addLast(new HttpObjectAggregator(1024 * 64));
        //上面是http相关的  下面是WebSocket相关的
        //此handler会处理一些复杂的繁重的操作
        //会处理一些握手的操作:handshaking(opening handshake,closing handshake,ping,pong)
        //对于WebSocket来说,数据都是以frames的形式传递的,不同的数据类型对应不同的frame
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

        //自定义处理器
        pipeline.addLast(new ChatHandler());

    }
}

3. 聊天 handler


/**
 - 自定义助手类
 - SimpleChannelInboundHandler 对于请求来说,等于入站
 - TextWebSocketFrame 用于websocket专门处理的文本数据对象,Frame是消息的载体
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    public static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {


        //客户端传输的消息
        String content = msg.text();
        System.out.println("客户端传输的消息:" + content);

        Channel channel = ctx.channel();
        String currentLongChannelId = channel.id().asLongText();
        String currentShortChannelId = channel.id().asShortText();

        System.out.println("channelId:" + currentLongChannelId + "short:" + currentShortChannelId);
        //需要用Frame去传递
        channel.writeAndFlush(new TextWebSocketFrame("服务器时间" + System.currentTimeMillis()));

    }

}