【问题标题】:ReadableByteChannel.read(ByteBuffer dest) reads capped at 8KB. Why?ReadableByteChannel.read(ByteBuffer dest) 读取上限为 8KB。为什么?
【发布时间】:2011-04-12 17:16:14
【问题描述】:

我有一些代码:

  1. ReadableByteChannel 读取到ByteBuffer
  2. 记录传输的字节,
  3. 暂停几十到几百毫秒,
  4. ByteBuffer 传递给WritableByteChannel

一些细节:

  • 两个通道都是 TCP/IP 套接字。
  • 总连接读取大小为几十兆。
  • 源套接字(ReadableByteChannel 从中获取字节)在同一台机器上。
  • HP DL380s 上的 Debian Lenny 64 位
  • Sun Java 1.6.0 更新 20

问题是,无论分配多大的 ByteBuffer,无论是使用.allocate() 还是.allocateDirect(),读入 ByteBuffer 的字节数最大为 8KB。我的目标 ByteBuffer 大小是 256KB,这只是一小部分(1/32nd)被使用。大约 10% 的时间只读入了 2896 个字节。

我检查了操作系统 TCP 缓冲区设置,它们看起来不错。观察 netstat 关于缓冲区中有多少字节的报告证实了这一点——两者的套接字缓冲区中的数据都超过了 8KB。

tcp        0 192384 1.2.3.4:8088     1.2.3.4:53404    ESTABLISHED
tcp6  110144      0 1.2.3.4:53404    1.2.3.4:8088     ESTABLISHED

这里最突出的一点是 TCP 和 TCP6 的混合,但我认为这应该不是问题。在上面的输出中,我的 Java 客户端位于端口 53404 上。

我尝试将套接字属性设置为支持带宽而不是延迟,但没有改变。

Socket socket = new Socket(host.getHostName(), host.getPort());
socket.setPerformancePreferences(1, 0, 2);  //bw > connection time > latency

当我记录 socket.getReceiveBufferSize() 的值时,它始终报告只有 43856 个字节。虽然它比我想要的要小,但它仍然超过 8KB。 (这也不是一个非常整数的数字,这是我所预料的。)

我真的很困惑这里的问题。理论上,AFAIK,这不应该发生。 “降级”到基于流的解决方案是不可取的,尽管如果找不到解决方案,我们下一步就是这样做。

我错过了什么?我能做些什么来纠正它?

【问题讨论】:

    标签: java sockets channel bytebuffer


    【解决方案1】:

    好的,我找到了问题! (如果有人遇到同样的问题,我会回答我自己的问题。)

    我不是直接从Socket 实例中实例化ReadableByteChannel,而是从HttpEntity.getContent() (Apache HTTP Commons Client) 方法返回的InputStream 中实例化。 HTTP Commons 客户端很早就通过DefaultHttpClientConnection.bind() 方法传递了套接字。我不明白的是,我认为 Channel 是埋在 HTTP Commons Client 实现中的 BufferedInputStream 实例。 (8KB 恰好是 Java 6 的默认值。)

    因此,我的解决方案是从原始 Socket 实例中获取 ReadableByteChannel

    【讨论】:

      猜你喜欢
      • 2011-01-27
      • 2023-03-04
      • 2017-06-08
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-03
      • 2020-06-22
      相关资源
      最近更新 更多