1

我有一些代码:

  1. 从 a 读ReadableByteChannel入 a ByteBuffer
  2. 记下传输的字节,
  3. 暂停几十到几百毫秒,
  4. 传递ByteBuffer到 a 上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,这不应该发生。“降级”到基于流的解决方案是不可取的,尽管如果找不到解决方案,这就是我们接下来要去的地方。

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

4

1 回答 1

0

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

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

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

于 2010-09-16T12:18:55.290 回答