【发布时间】: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