【问题标题】:Can Java NIO.2 read the ByteBuffer out of order?Java NIO.2 可以乱序读取 ByteBuffer 吗?
【发布时间】:2016-03-22 08:55:43
【问题描述】:

对于任何感兴趣的人,这个问题的答案是否定的,套接字不会乱序读取缓冲区。


AsynchronousSocketChannel 是否可以乱序读取字节?我正在努力调试我的问题开始的地方,我的协议将对象序列化为 32k 并将它们写入套接字,如下所示:

AsynchronousSocketChannel socket; ...

// serialize packet

ByteBuffer base; // serialized buffer (unknown size, size growns as needed with limit of 32k)

for (int j1 = 0; j1 < 6 && base.remaining() > 0; j1++) { // limit to 6 tries

    socket.write(base).get(15, TimeUnit.SECONDS);
    if (base.remaining() > 0) {
        // aparently, if the write operation could write everything at once, we wouldnt have an issue
    }
}

此写操作不是并发的,它与锁同步。我使用这样的标准读取操作:

AsynchronousSocketChannel socket; ...

Future<Integer> reading = socket.read(getReadBuffer()); // the read buffer is 8k big

// consume the buffer also not concurrently

我每秒最多可以写入 1000 个数据包,每个数据包最多 1000 个字节,但最终一个或另一个客户端会中断。如果数据包更大,它可以处理而不中断的频率会更低,如果我每秒写大约 8 个,40.000 字节的数据包会中断。

示例:我写了 5 个字节(1,2,3,4,5),缓冲区足够大,可以一次写入所有内容,但操作决定停止缓冲区中的剩余字节(这应该是正常的 TCP行为),所以假设操作写入 1,2,3,停止并写入剩余的 4,5(而 buf.remain > 0 { write }),在阅读时,很可能我会先阅读 4,5,然后1,2,3 之后,这不应该发生。

虽然在本地主机上一切正常,但在同一台机器外(仍然是同一网络/路由器)它不会工作。

我不会翻转缓冲区来写入/读取。我可以确保它不是序列化的问题,并且服务器和客户端都是单线程的。我忘了做什么?有关如何解决此问题的任何建议?

【问题讨论】:

  • 问题出在您没有发布的代码中。可能在读取或写入之间的缓冲区处理中。一个常见的错误,例如,当您的 read() 在第一个数据包之后获得下一个数据包的一部分时,您无法将这些字节正确地合并到您接下来读取的数据包中。

标签: java multithreading sockets nio


【解决方案1】:

如果您真正想要的只是同步 I/O,那么您为什么要使用异步 I/O,而这正是您从该代码中得到的,那么您不清楚为什么要使用异步 I/O。你最好用普通的SocketChannel

我不会翻转缓冲区来写入/读取。

你必须。您必须在write() 之前flip(),然后在compact() 之后,其中“之后”在这种情况下的含义与上述相同。

【讨论】:

  • 是的,我知道它是异步的,但是我在获取 Future 对象后正在测试缓冲区,我只是将它放在一行中,因为我不需要 Future 的返回值。关于翻转,我应该还是必须?不用翻转也可以吗?
  • @FurmigaHumana 查看编辑。当然,你必须翻转。您在实施时遇到什么问题?
  • 在你所说的之后,我意识到我并不完全了解如何正确使用 ByteBuffer。我的问题是我将其余部分写在错误的索引中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
相关资源
最近更新 更多