ReadableByteChannel.read(ByteBuffer dest)读取上限为8KB。为什么?

时间:2010-09-15 14:14:16

标签: java sockets channel bytebuffer

我有一些代码:

  1. ReadableByteChannel读取到ByteBuffer
  2. 记录转移的字节,
  3. 暂停几十到几百毫秒,
  4. ByteBuffer传递给WritableByteChannel
  5. 一些细节:

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

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

    我已经检查了OS 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,这不应该发生。将“降级”降级为基于流的解决方案是不可取的,尽管如果找不到解决方案,这就是我们下一步的目标。

    我错过了什么?我该怎么做才能纠正它?

1 个答案:

答案 0 :(得分:0)

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

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

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