Netty实战(三):客户端与服务端双向通信

2,860 阅读2分钟
原文链接: fageiguanbing.gitee.io

本章实现功能为:客户端连接成功之后,向服务端发送数据,服务端接收到数据之后,向客户端返回一段数据。

客户端发送数据到服务端

之前提到过,处理业务逻辑是在handler中进行的,现在我们就添加一个 handler

.handler(new ChannelInitializer<SocketChannel>() {
    @Override
    public void initChannel(SocketChannel ch) {
        ch.pipeline().addLast(new FirstClientHandler());
    }
});
向服务端发送数据的业务逻辑
public class FirstClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        System.out.println("客户端开始写出数据");
        // 1.创建将要写出的数据
        ByteBuf buffer = getByteBuf(ctx);
        // 2.发送数据
        ctx.channel().writeAndFlush(buffer);
    }

    private ByteBuf getByteBuf(ChannelHandlerContext ctx) {
        // byte类型的数据
        byte[] bytes = "这里是将要写往服务端的数据".getBytes(Charset.forName("utf-8"));
		// 申请一个数据结构存储信息
        ByteBuf buffer = ctx.alloc().buffer();
		// 将信息放入数据结构中
        buffer.writeBytes(bytes);
        return buffer;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("客户端读到数据:" + byteBuf.toString(Charset.forName("utf-8")));
    }
}

说明:

  • 1.ChannelInboundHandlerAdapter 是实现了 io.netty.channel.ChannelHandler 这个接口的, 所有实现了该接口的 handler 都具有以下生命周期:
状态 描述
ChannelUnregistered channel已经创建,但还未注册到EventLoop
ChannelRegistered channel已经被注册到了EventLoop
ChannelActive channel处于连接到远程节点的状态,它现在可以接受和发送数据了
ChannelInactive channel没有连接到远程节点
  • 2.这个 handler 继承 ChannelInboundHandlerAdapter ,这个handler也有它附加的方法,其中 channelRead 指从channel读到数据时调用的方法。

服务端读取客户端数据

和客户端一样,添加一个处理业务逻辑的handler

.childHandler(new ChannelInitializer<NioSocketChannel>() {
    @Override
    protected void initChannel(NioSocketChannel ch) {
        ch.pipeline().addLast(new FirstServerHandler());
    }
});
服务端接受客户端数据以及向客户端返回数据的业务逻辑
public class FirstServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("服务端读到数据:" + byteBuf.toString(Charset.forName("utf-8")));
        // 回复数据到客户端
        System.out.println("服务端开始写出数据");
        // 创建需要回复的数据
        ByteBuf out = getByteBuf(ctx);
        // 发送数据
        ctx.channel().writeAndFlush(out);
    }

    private ByteBuf getByteBuf(ChannelHandlerContext ctx) {
        byte[] bytes = "这里是服务端将要写出发往客户端的数据".getBytes(Charset.forName("utf-8"));
		// 申请一个数据结构存储信息
        ByteBuf buffer = ctx.alloc().buffer();
		// 将信息放入数据结构中
        buffer.writeBytes(bytes);
        return buffer;
    }
}

参考资料

本文由 发给官兵 创作,采用 CC BY 3.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出 处。如转载至微信公众号,请在文末添加作者公众号二维码。