关于Netty中连接到了客户端,只调用了channelReadComplete,没走channelRead

关于Netty中连接到了客户端,只调用了channelReadComplete,没走channelRead。
今天自己练习的时候,根据网上的代码进行测试。

public class TcpServerHandler extends SimpleChannelInboundHandler<ByteBuf> {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    @Qualifier("businessGroup")
    private EventExecutorGroup businessGroup;

    /**
     * 使用
     *
     * @param ctx
     * @param byteBuf
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) {
        String content = byteBuf.toString(StandardCharsets.UTF_8);
        log.info("TCP服务端接收到消息:{}", content);


        ByteBuf buf = Unpooled.copiedBuffer("TCP已经接收到消息:".getBytes(StandardCharsets.UTF_8));

        businessGroup.execute(() -> {
            try {
                rocketMQTemplate.convertAndSend("zp-consumer-rockrt-netty-test", content);
                send2client(ctx, buf.array());
            } catch (Throwable e) {
                log.error("TCP数据接收处理出错", e);
                ByteBuf err = Unpooled.copiedBuffer("系统错误:".getBytes(StandardCharsets.UTF_8));
                send2client(ctx, err.array());
            }
        });

    }

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

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("TCP数据接收处理出错:", cause);
    }

    /**
     * 返回消息给客户端
     *
     * @param ctx
     * @param msg
     */
    void send2client(ChannelHandlerContext ctx, byte[] msg) {
        ByteBuf buf = Unpooled.buffer(msg.length + 1);
        buf.writeBytes(msg);
        buf.writeByte(MsgUtil.DELIMITER);
        ctx.channel().writeAndFlush(buf).addListener(future -> {
            if (!future.isSuccess()) {
                log.error("TCP发送给客户端消息失败");
            }
        });
    }
上图为ServerHandler代码。

/**
* netty服务(TCP)
*/
@Slf4j
@Component
public class NettyTcpServer implements ApplicationListener<ApplicationStartedEvent> {

  @Value("${netty.tcp.port}")
  private int port;
  
  @Value("${netty.tcp.read-timeout}")
  private int readTimeOut;

  @Autowired
  @Qualifier("bossGroup")
  private NioEventLoopGroup bossGroup;

  @Autowired
  @Qualifier("workerGroup")
  private NioEventLoopGroup workerGroup;
  
  @Autowired
  @Qualifier("businessGroup")
  private EventExecutorGroup businessGroup;

  @Autowired
  private TcpServerHandler tcpServerHandler;

  @Autowired
  private MyServerHandler myServerHandler;

  private ChannelFuture channelFuture;
  private org.slf4j.Logger logger = LoggerFactory.getLogger(NettyTcpServer.class);
  /**
   * 启动Server
   *
   */
  @Override
  public void onApplicationEvent(ApplicationStartedEvent event) {

  	try {
          ServerBootstrap serverBootstrap = new ServerBootstrap();
          serverBootstrap.group(bossGroup, workerGroup)
                  .channel(NioServerSocketChannel.class)
                  .childHandler(new ChannelInitializer<SocketChannel>() { //
  					@Override
  					public void initChannel(SocketChannel channel) throws Exception {
                          //        日志打印
                          channel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                          // 基于换行符号
//                            channel.pipeline().addLast(new LineBasedFrameDecoder(1024));
                          // 解码转String,注意调整自己的编码格式GBK,UTF-8
                          channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
                          // 解码转String,注意调整自己的编码格式GBK,UTF-8
                          channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
//                            channel.pipeline().addLast(new IdleStateHandler(readTimeOut, 0, 0, TimeUnit.MINUTES));
							// 1024表示单条消息的最大长度,解码器在查找分隔符的时候,达到该长度还没找到的话会抛异常
//                            channel.pipeline().addLast(
//									new DelimiterBasedFrameDecoder(1024, Unpooled.copiedBuffer(new byte[] { MsgUtil.DELIMITER }),
//											Unpooled.copiedBuffer(new byte[] { MsgUtil.DELIMITER, MsgUtil.DELIMITER })));
                          channel.pipeline().addLast(myServerHandler);
  					}
  				})
                  .option(ChannelOption.SO_BACKLOG, 128) //服务端可连接队列数,对应TCP/IP协议listen函数中backlog参数
                  .childOption(ChannelOption.TCP_NODELAY, true)//立即写出
                  .childOption(ChannelOption.SO_KEEPALIVE, true);//长连接

          channelFuture = serverBootstrap.bind(port).sync();
          if (channelFuture.isSuccess()) {
  			log.info("TCP服务启动完毕,port={}", port);
          }

  	}catch(Exception e) {
  		log.info("TCP服务启动失败", e);
  	}finally {
          if (null != channelFuture && channelFuture.isSuccess()){
              logger.info("netty server start done 、netty服务已经开始");
          }else {
              logger.error("netty server start error、netty服务开始错误");
          }
      }
  }

  /**
   * 销毁资源
   */
  @PreDestroy
  public void destroy() {
      bossGroup.shutdownGracefully().syncUninterruptibly();
      workerGroup.shutdownGracefully().syncUninterruptibly();
      log.info("TCP服务关闭成功");
  }
}

上图因为添加了下面这段代码

// 基于换行符号

channel.pipeline().addLast(new LineBasedFrameDecoder(1024));

导致只调用了channelReadComplete,没走channelRead。

在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java通过Netty连接服务端和客户端的基本步骤如下: 1. 引入Netty依赖:在Maven添加Netty依赖,或者手动下载并添加到项目。 2. 创建客户端和服务端的Bootstrap:通过Bootstrap类创建客户端和服务端的启动类,设置相关的参数和处理器。 3. 客户端连接服务端:通过客户端的Bootstrap连接服务端的IP和端口。 4. 服务端监听客户端连接:通过服务端的Bootstrap监听客户端连接,建立连接后获取对应的Channel。 5. 处理服务端请求:在服务端的ChannelHandler处理客户端的请求,包括连接数据库获取数据。 6. 发送数据到客户端:在服务端的ChannelHandler将处理结果发送到客户端。 以下是一个简单的示例代码: 客户端: ``` EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel channel) throws Exception { // 添加处理器 } }); ChannelFuture future = bootstrap.connect("localhost", 8888).sync(); future.channel().closeFuture().sync(); ``` 服务端: ``` EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); Bootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel channel) throws Exception { // 添加处理器 } }); ChannelFuture future = bootstrap.bind(8888).sync(); future.channel().closeFuture().sync(); ``` 在处理器连接数据库,获取数据,发送数据到客户端的代码如下: ``` public class ServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // 连接数据库,获取数据 // 将数据发送到客户端 ctx.writeAndFlush(data); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱折磨键盘的大鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值