Netty (3) - to achieve the client and server-side two-way communication

A basic idea

Read and write logic processing stages are started by adding to the logic processing chain Pipeline logical processor to read and write data in the logical connection.

  1. Client connection success logic processor callback channelActive()method

  2. The client and server receives data back to the calling of each other's logic processor channelRead()method.

  3. The client and server to write data to the other call writeAndFlush()method

  4. Binary data transmission carrier client and server interaction isByteBuf

II. Communication Process

[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-lxx6KkVY-1580725870430) (http://note.youdao.com/yws/res/9840/76DC2AB9464A4D1882346E496B1C9518)]

III. Code implementation

  • NIOServer
/**
 * @Auther: ARong
 * @Description: 服务端-客户端双向通信,服务端在接收到客户端信息后向客户端发出响应
 */
public class NIOServer {
    public static void main(String[] args) {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(); // 监听组
        NioEventLoopGroup workerGroup = new NioEventLoopGroup(); // 工作组

        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class) //NIO模式
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    // 初始化channel
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new FirstServerHandler());
                    }
                }).bind(8000);
    }
}

  • NIOClient
/**
 * @Auther: ARong
 * @Description: 服务端-客户端双向通信,客户端向服务端发送信息
 */
public class NIOClient {
    public static void main(String[] args) throws InterruptedException {
        Bootstrap bootstrap = new Bootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();

        bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                // 责任链模式,添加第一次连接的客户端处理逻辑
                ch.pipeline().addLast(new FirstClientHandler());
            }
        });

        Channel channel = bootstrap.connect("127.0.0.1", 8000).channel();
        String message = String.format("HelloWorld From %s", new SimpleDateFormat("hh:mm:ss").format(new Date()));
        channel.writeAndFlush(message);
    }
}
  • FirstServerHandler
/**
 * @Auther: ARong
 * @Description: 服务端被首次连接的处理逻辑
 */
public class FirstServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    /*
     * @Author ARong
     * @Description 接收到服务端消息时触发
     * @Param [ctx, msg]
     * @return void
     **/
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println(String.format("服务端读取到数据%s From %s",
                byteBuf.toString(Charset.forName("utf-8")),
                getCurTime()));

        ByteBuf byteBuf1 = getByteBuf(ctx);
        ctx.channel().writeAndFlush(byteBuf1);
    }

    /*
     * @Author ARong
     * @Description 获取二进制抽象 ByteBuf
     * @Param [ctx]
     * @return io.netty.buffer.ByteBuf
     **/
    private ByteBuf getByteBuf(ChannelHandlerContext ctx) {
        // 获取二进制抽象 ByteBuf
        ByteBuf buffer = ctx.alloc().buffer();

        // 准备数据,指定字符串的字符集为 utf-8
        String response = String.format("服务端返回HelloWorld From %s", getCurTime());
        byte[] bytes = response.getBytes(Charset.forName("utf-8"));

        // 填充数据到 ByteBuf
        buffer.writeBytes(bytes);

        return buffer;
    }

    private String getCurTime() {
        return new SimpleDateFormat("hh:mm:ss").format(new Date());
    }
}
  • FirstClientHandler
/**
 * @Auther: ARong
 * @Description: 首次连接的客户端处理逻辑
 */
public class FirstClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    /*
     * @Author ARong
     * @Description 客户端与服务端首次连接的处理逻辑
     * @Param [ctx]
     * @return void
     **/
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 编码数据
        ByteBuf byteBuf = getByteBuf(ctx);
        // 写回给服务端
        ctx.channel().writeAndFlush(byteBuf);
    }

    @Override
    /*
     * @Author ARong
     * @Description 接收到服务端消息时触发
     * @Param [ctx, msg]
     * @return void
     **/
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println(String.format("客户端读取到数据%s From %s",
                byteBuf.toString(Charset.forName("utf-8")),
                getCurTime()));
    }

    /*
     * @Author ARong
     * @Description 获取二进制抽象 ByteBuf
     * @Param [ctx]
     * @return io.netty.buffer.ByteBuf
     **/
    private ByteBuf getByteBuf(ChannelHandlerContext ctx) {
        // 获取二进制抽象 ByteBuf
        ByteBuf buffer = ctx.alloc().buffer();

        // 准备数据,指定字符串的字符集为 utf-8
        String response = String.format("客户端返回HelloWorld From %s", getCurTime());
        byte[] bytes = response.getBytes(Charset.forName("utf-8"));

        // 填充数据到 ByteBuf
        buffer.writeBytes(bytes);

        return buffer;
    }

    private String getCurTime() {
        return new SimpleDateFormat("hh:mm:ss").format(new Date());
    }
}

In turn starts the client and server, two-way communication:

Here Insert Picture Description

Published 309 original articles · won praise 205 · Views 300,000 +

Guess you like

Origin blog.csdn.net/pbrlovejava/article/details/104160163