Netty服务端与客户端通信

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/uk8692/article/details/79602020

最近开始学习Netty,

服务端:

public class TimeServer {

    public void bind(int port) throws Exception {
        /**
         * NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器,
         * Netty提供了许多不同的EventLoopGroup的实现用来处理不同传输协议,
         * 在这个例子中我们实现了一个服务端的应用,因此会有2个NioEventLoopGroup会被使用。
         * 第一个经常被叫做‘boss’,用来接收进来的连接。
         * 第二个经常被叫做‘worker’,用来处理已经被接收的连接。
         */
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap server = new ServerBootstrap();
            server.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childHandler(new ChildChannelHandler());

            //绑定端口,同步等待成功
            ChannelFuture future = server.bind(port).sync();
            //等待服务端监听端口关闭
            future.channel().closeFuture().sync();
        } finally {
            //优雅退出,释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }

    private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{
        @Override
        protected void initChannel(SocketChannel socketChannel) throws Exception {
            socketChannel.pipeline().addLast(new TimeServerHandler());
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 8888;
        new TimeServer().bind(port); 
    }

}
public class TimeServerHandler extends ChannelHandlerAdapter{

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        /*ByteBuf byteBuf = (ByteBuf) msg;
        String message = new String(byteBuf.array());*/
        ByteBuf byteBuf = (ByteBuf) msg;
        byte[] buf = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(buf);
        String message = new String(buf,"UTF-8");
        System.out.println("the server received msg:"+message);

        String resText = "你好,我已经收到你的消息!"+new Date(System.currentTimeMillis()).toString();
        ByteBuf writeByteBuf = Unpooled.copiedBuffer(resText.getBytes());
        ctx.write(writeByteBuf);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println(cause.getMessage());
        ctx.close();
    }

}

客户端:

public class TimeClinet {

    public void connect(String host, int port) throws Exception {
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            Bootstrap server = new Bootstrap();
            server.group(workerGroup)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new TimeClientHandler());
                        }
                });
            // 发起异步连接操作
            ChannelFuture future = server.connect(host, port).sync();
            // 等待客户端链路关闭
            future.channel().closeFuture().sync();
        } finally {
            //优雅退出,释放NIO线程组
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 8888;
        new TimeClinet().connect("127.0.0.1", port);
    }

}
public class TimeClientHandler extends ChannelHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String msg = "你好!TimeServer。。。。。。。。。";
        ByteBuf byteBuf = Unpooled.copiedBuffer(msg.getBytes());
        ctx.writeAndFlush(byteBuf);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        byte[] buf = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(buf);
        String message = new String(buf);
        System.out.println("Now is :" + message);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }

}

在这里,最初写这个代码的时候遇到了一点问题,那就是在服务端接收消息时,我的代码如下:

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        String message = new String(byteBuf.array());
        System.out.println("the server received msg:"+message);
    }

在调试的时候发现报错:
这里写图片描述

这里写图片描述

查看Netty底层源码,发现UnpooledUnsafeDirectByteBuf并不支持array()方法。
原来为了提升性能,Netty默认的I/O Buffer使用直接内存DirectByteBuf,可以减少Socket读写的内存拷贝,即著名的 ”零拷贝”。
由于是直接内存,因此无法直接转换成堆内存,因此它并不支持array()方法。用户需要自己做内存拷贝。

猜你喜欢

转载自blog.csdn.net/uk8692/article/details/79602020