【问题标题】:Blocking tcp packet receiving in Netty 4.x在 Netty 4.x 中阻止 tcp 数据包接收
【发布时间】:2015-08-13 16:55:02
【问题描述】:

如何阻止 netty 在 netty 4.x 中向客户端发送 ACK 响应?

我正在尝试控制 netty 中的 TCP 数据包接收速度,以便将这些数据包转发到另一台服务器。 Netty立即收到所有客户端数据包,但是netty需要更多时间将它们发送出去,所以客户端认为它发送到netty后就完成了。

所以,我想知道当 netty 将之前收到的数据包转发到另一台服务器时,如何阻止收到的数据包。

【问题讨论】:

    标签: proxy netty


    【解决方案1】:

    不确定是否真正理解您的问题。所以我尝试重新制定:

    • 我认为您的 Netty 服务器充当客户端和另一台服务器之间的代理。
    • 我想你想要做的是只有在你真正将转发的数据包发送到最终服务器时才将 ack 发送回客户端(最终服务器不一定会收到,但至少由 Netty 代理发送)。

    如果是这样,那么你应该使用转发数据包的future来回应ack,例如(伪代码):

    channelOrCtxToFinalServer.writeAndFlush(packetToForward).addListener(new ChannelFutureListener() {
      public void operationComplete(ChannelFuture future) {
        // Perform Ack write back
        ctxOfClientChannel.writeAndFlush(AckPacket);
      }
    });
    

    地点:

    • channelOrCtxToFinalServer 是从 Netty 代理连接到远程最终服务器的 ChannelHandlerContextChannel 之一,
    • ctxOfClientChannel 是来自您的Netty 处理程序的当前ChannelHandlerContext,它以public void channelRead(ChannelHandlerContext ctxOfClientChannel, Object packetToForward) 方法从客户端接收数据包。

    编辑: 对于大文件传输问题,您可以查看代理示例here

    特别要注意以下几点:

    • 使用同样的逻辑,注意从客户端一个接一个地接收数据:

      yourServerBootstrap..childOption(ChannelOption.AUTO_READ, false);
      // Allow to control one by one the speed of reception of client's packets
      
    • 在您的前端处理程序中:

      public void channelRead(final ChannelHandlerContext ctx, Object msg) {
          if (outboundChannel.isActive()) {
              outboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
                  @Override
                  public void operationComplete(ChannelFuture future) {
                      if (future.isSuccess()) {
                          // was able to flush out data, start to read the next chunk
                          ctx.channel().read();
                      } else {
                          future.channel().close();
                      }
                  }
              });
          }
      }
      
    • 最后,使用相同的逻辑向您的客户端添加最终确认(确认当然取决于您的协议):(参见herehere

      /**
       * Closes the specified channel after all queued write requests are flushed.
       */
      static void closeOnFlush(Channel ch) {
          if (ch.isActive()) {
              ch.writeAndFlush(AckPacket).addListener(ChannelFutureListener.CLOSE);
          }
      }
      

    【讨论】:

    • 谢谢 Frederic ~ 你明白了我的意思。但是你的建议并没有解决我的问题。原谅我英语不好。我有一个大文件需要转发(超过 6000kb)。首先,客户端(3 方客户端)在 1 秒内将其发送到 netty,并且客户端上的进度条显示为 100%。我认为 netty 接受所有文件并将它们缓存在缓冲区中。然后,开始转发。最后,向 clent 发送服务器响应。因此,客户端将长时间保持 100% 等待响应。我希望客户端等待网络转发每个数据包,而不是一次发送所有文件。
    • 也许我应该先问:你的处理程序和编码器/解码器是什么?这个问题的原因是:超过6000kb是通过几个数据包发送的,所以你当然也可以逐包管理转发到下一个服务器的数据包。但此外,您可以管理 Netty 服务器的“可读”属性,这样一旦它收到一个数据包,它将禁用传入通道(客户端通道)的读取过程,直到它完成对最终服务器的写入,然后重新激活客户端频道的可读性。这样做可以管理数据包接收的速度。
    • 我编辑了我的回答,以通过 Netty 的代理示例来解释我的想法......希望它可以帮助你......
    • 我已经尝试使用“SetAutoRead”,并且可以阻止 netty 将缓冲区发送到我的处理程序。但我无法阻止客户端向 netty 发送数据包。也许客户端将它们发送到 netty 的缓存。 'Readable' 属性只是阻止缓存发送缓冲区到处理程序。我认为netty在低层自动接收数据包。一个应用层协议会同时发送所有的数据和很多包,比如一个HttpRequest,POP3,它们是不可控的?顺便说一句,我使用了许多处理程序来编码和解码缓冲区。需要我发送我的代码吗?非常感谢:P
    • Auto_read 阻止客户端向 Netty 服务器发送任何内容,因为它阻止了读取操作,因此阻止了来自客户端的传入消息。在 auto_read 上查看其他问题:stackoverflow.com/questions/28273305/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 2015-09-25
    • 2013-04-03
    • 2019-04-28
    • 2017-01-27
    相关资源
    最近更新 更多