BIO&NIO&AIO&Netty 初识四 Netty

netty-socket

socket实现

server

netty服务类

public class NettySocketServer {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup(8);
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workGroup).option(ChannelOption.SO_BACKLOG, 1024)
                .channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel channel) {
                        channel.pipeline().addLast(new IdleStateHandler(3, 0, 0, TimeUnit.SECONDS));
                        channel.pipeline().addLast(new NettySocketHandler());
                    }
                });
            ChannelFuture channelFuture = serverBootstrap.bind(9000).sync();
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

    }

}

netty业务处理类

public class NettySocketHandler extends SimpleChannelInboundHandler {

    @Override
    protected void channelRead0(ChannelHandlerContext chc, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf)msg;
        SocketAddress socketAddress = chc.channel().remoteAddress();
        System.out.println("收到客户端:" + socketAddress + "的消息:" + buf.toString(CharsetUtil.UTF_8));
        ByteBuf sendBuf = Unpooled.copiedBuffer("收到".getBytes(CharsetUtil.UTF_8));
        chc.writeAndFlush(sendBuf);
    }

    int num = 0;

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        IdleStateEvent event = (IdleStateEvent)evt;
        if (event.state().equals(IdleState.READER_IDLE)) {
            num++;
        }
        if (num > 3) {
            System.out.println("3次未收到心跳");
            ctx.channel().close();
        }
    }
}

client

netty客户端

public class NettySocketClient {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup workGroup = new NioEventLoopGroup(8);
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(workGroup).channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel channel) {
                        channel.pipeline().addLast(new NettySocketClientHandler());
                    }
                });
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9000).sync();
            Scanner scanner = new Scanner(System.in);
            while (true) {
                String msg = scanner.nextLine();
                ByteBuf sendBuf = Unpooled.copiedBuffer(msg.getBytes(CharsetUtil.UTF_8));
                channelFuture.channel().writeAndFlush(sendBuf);
            }
        } finally {
            workGroup.shutdownGracefully();
        }

    }

}

netty客户端业务处理类

public class NettySocketClientHandler extends SimpleChannelInboundHandler {

    @Override
    protected void channelRead0(ChannelHandlerContext chc, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf)msg;
        System.out.println("收到服务端发送的消息:" + buf.toString(CharsetUtil.UTF_8));
    }

}

netty-websocket

用netty实现websocket

server

websocket服务端

public class NettyWebSocketServer {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup(8);

        try {
            ServerBootstrap serverBootstrap =
                new ServerBootstrap().group(bossGroup, workGroup).option(ChannelOption.SO_BACKLOG, 1024)
                    .channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel channel) throws Exception {
                            channel.pipeline().addLast(new HttpRequestDecoder());
                            channel.pipeline().addLast(new HttpResponseEncoder());
                            channel.pipeline().addLast(new HttpObjectAggregator(8192));
                            channel.pipeline().addLast(new WebSocketServerProtocolHandler("/ws"));
                            channel.pipeline().addLast(new NettyWebSocketHandler());
                        }
                    });
            ChannelFuture channelFuture = serverBootstrap.bind(9000).sync();
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

    }
}

websocket业务处理类

public class MyHttpChannelHandler extends SimpleChannelInboundHandler {

    @Override
    protected void channelRead0(ChannelHandlerContext chc, Object msg) throws Exception {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=utf-8");
        response.content().writeBytes("你好".getBytes());
        chc.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }
}

client

在线websocket客户端测试
可以使用上面网站进行测试,连接地址写ws://localhost:9000/ws

netty-http

用netty实现http服务器

server

http服务

public class HttpNettyService {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup(8);
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap()
                // 设置工作组
                .group(bossGroup, workGroup)
                // 设置管道类型
                .channel(NioServerSocketChannel.class)
                // 设置参数
                .option(ChannelOption.SO_BACKLOG, 1024)
                // 设置handler
                .childHandler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(Channel channel) throws Exception {
                        channel.pipeline().addLast(new HttpRequestDecoder());
                        channel.pipeline().addLast(new HttpResponseEncoder());
                        channel.pipeline().addLast(new MyHttpChannelHandler());
                    }
                });
            ChannelFuture channelFuture = serverBootstrap.bind(9000).sync();
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}

http业务处理类

public class MyHttpChannelHandler extends SimpleChannelInboundHandler {

    @Override
    protected void channelRead0(ChannelHandlerContext chc, Object msg) throws Exception {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=utf-8");
        response.content().writeBytes("你好".getBytes());
        chc.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }
}

client

浏览器访问:http://localhost:9000

总结

  • netty底层是对nio的封装,使用户只需关系具体业务实现,操作更加简单
  • BossGroup(NioEventLoop线程组)用来处理连接请求
  • WorkerGroup(NioEventLoop线程组,默认逻辑核数*2)用来处理读写请求
  • netty默认使用零拷贝技术,接收到的数据放到直接内存中(DirectByteBuffer,堆外内存)零拷贝技术减少用户态到内核态的拷贝io,使读写效率更快(但是申请内存空间效率差,所以netty使用池化技术,提前申请DirectByteBuffer内存池,使用时直接从池中获取)
  • 解决nio的空轮训bug:selector.select()方法 nio会有bug,有时候没有事件发生也会触发,并且永远都不会获得事件,cpu会飙升到100%
    netty 会记录次数,超过512次后会重新new一个新的select替换掉旧的
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页