Netty(3)-实现客户端与服务端的双向通信

爱被打了一巴掌 2023-07-03 06:29 70阅读 0赞

文章目录

      • 一.基本思路
      • 二.通信流程
      • 三.代码实现

一.基本思路

读写逻辑处理均是启动阶段通过给逻辑处理链Pipeline添加逻辑处理器实现连接数据的读写逻辑。

  1. 客户端连接成功回调逻辑处理器的channelActive()方法
  2. 客户端和服务端接收到对方的数据回调用各自逻辑处理器的channelRead()方法。
  3. 客户端和服务端向对方写数据调用writeAndFlush()方法
  4. 客户端和服务端交互的二进制数据传输载体为ByteBuf

二.通信流程

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lxx6KkVY-1580725870430)(http://note.youdao.com/yws/res/9840/76DC2AB9464A4D1882346E496B1C9518)\]

三.代码实现

  • NIOServer

    /* @Auther: ARong @Description: 服务端-客户端双向通信,服务端在接收到客户端信息后向客户端发出响应 /
    public class NIOServer {

    1. public static void main(String[] args) {
    2. ServerBootstrap serverBootstrap = new ServerBootstrap();
    3. NioEventLoopGroup bossGroup = new NioEventLoopGroup(); // 监听组
    4. NioEventLoopGroup workerGroup = new NioEventLoopGroup(); // 工作组
    5. serverBootstrap.group(bossGroup, workerGroup)
    6. .channel(NioServerSocketChannel.class) //NIO模式
    7. .childHandler(new ChannelInitializer<SocketChannel>() {
    8. @Override
    9. // 初始化channel
    10. protected void initChannel(SocketChannel ch) throws Exception {
    11. ch.pipeline().addLast(new FirstServerHandler());
    12. }
    13. }).bind(8000);
    14. }

    }

  • NIOClient

    /* @Auther: ARong @Description: 服务端-客户端双向通信,客户端向服务端发送信息 /
    public class NIOClient {

    1. public static void main(String[] args) throws InterruptedException {
    2. Bootstrap bootstrap = new Bootstrap();
    3. NioEventLoopGroup group = new NioEventLoopGroup();
    4. bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
    5. @Override
    6. protected void initChannel(SocketChannel ch) throws Exception {
    7. // 责任链模式,添加第一次连接的客户端处理逻辑
    8. ch.pipeline().addLast(new FirstClientHandler());
    9. }
    10. });
    11. Channel channel = bootstrap.connect("127.0.0.1", 8000).channel();
    12. String message = String.format("HelloWorld From %s", new SimpleDateFormat("hh:mm:ss").format(new Date()));
    13. channel.writeAndFlush(message);
    14. }

    }

  • FirstServerHandler

    /* @Auther: ARong @Description: 服务端被首次连接的处理逻辑 /
    public class FirstServerHandler extends ChannelInboundHandlerAdapter {

    1. @Override
    2. /* * @Author ARong * @Description 接收到服务端消息时触发 * @Param [ctx, msg] * @return void **/
    3. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    4. ByteBuf byteBuf = (ByteBuf) msg;
    5. System.out.println(String.format("服务端读取到数据%s From %s",
    6. byteBuf.toString(Charset.forName("utf-8")),
    7. getCurTime()));
    8. ByteBuf byteBuf1 = getByteBuf(ctx);
    9. ctx.channel().writeAndFlush(byteBuf1);
    10. }
    11. /* * @Author ARong * @Description 获取二进制抽象 ByteBuf * @Param [ctx] * @return io.netty.buffer.ByteBuf **/
    12. private ByteBuf getByteBuf(ChannelHandlerContext ctx) {
    13. // 获取二进制抽象 ByteBuf
    14. ByteBuf buffer = ctx.alloc().buffer();
    15. // 准备数据,指定字符串的字符集为 utf-8
    16. String response = String.format("服务端返回HelloWorld From %s", getCurTime());
    17. byte[] bytes = response.getBytes(Charset.forName("utf-8"));
    18. // 填充数据到 ByteBuf
    19. buffer.writeBytes(bytes);
    20. return buffer;
    21. }
    22. private String getCurTime() {
    23. return new SimpleDateFormat("hh:mm:ss").format(new Date());
    24. }

    }

  • FirstClientHandler

    /* @Auther: ARong @Description: 首次连接的客户端处理逻辑 /
    public class FirstClientHandler extends ChannelInboundHandlerAdapter {

    1. @Override
    2. /* * @Author ARong * @Description 客户端与服务端首次连接的处理逻辑 * @Param [ctx] * @return void **/
    3. public void channelActive(ChannelHandlerContext ctx) throws Exception {
    4. // 编码数据
    5. ByteBuf byteBuf = getByteBuf(ctx);
    6. // 写回给服务端
    7. ctx.channel().writeAndFlush(byteBuf);
    8. }
    9. @Override
    10. /* * @Author ARong * @Description 接收到服务端消息时触发 * @Param [ctx, msg] * @return void **/
    11. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    12. ByteBuf byteBuf = (ByteBuf) msg;
    13. System.out.println(String.format("客户端读取到数据%s From %s",
    14. byteBuf.toString(Charset.forName("utf-8")),
    15. getCurTime()));
    16. }
    17. /* * @Author ARong * @Description 获取二进制抽象 ByteBuf * @Param [ctx] * @return io.netty.buffer.ByteBuf **/
    18. private ByteBuf getByteBuf(ChannelHandlerContext ctx) {
    19. // 获取二进制抽象 ByteBuf
    20. ByteBuf buffer = ctx.alloc().buffer();
    21. // 准备数据,指定字符串的字符集为 utf-8
    22. String response = String.format("客户端返回HelloWorld From %s", getCurTime());
    23. byte[] bytes = response.getBytes(Charset.forName("utf-8"));
    24. // 填充数据到 ByteBuf
    25. buffer.writeBytes(bytes);
    26. return buffer;
    27. }
    28. private String getCurTime() {
    29. return new SimpleDateFormat("hh:mm:ss").format(new Date());
    30. }

    }

依次启动客户端和服务端,实现双向通信:

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,70人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Netty实现客户服务通信

    实现一个客户端与服务端通信的程序,可以使用socket网络编程来实现,而Netty作为一个封装了JDK的NIO通讯的异步事件驱动的网络应用框架,也同样可以实现。 1.创建M