JavaNIO:发送大消息会很快导致数据包被截断和数据丢失
我遇到了一个棘手的问题,从Java(NIO)服务器(运行Linux)快速连续地向客户机发送多条大型消息会导致数据包被截断。消息必须很大且发送速度非常快,才能发生问题。下面是我的代码所做的基本内容(不是实际的代码,而是或多或少发生的事情): 存在数据丢失,并且分组开始一起运行,使得分组5的开始(在本例中)到达与分组4的开始相同的消息中。它不仅仅是截断,而是将消息一起运行 我认为这与TCP缓冲区或“窗口大小”有关,或者这里的服务器提供数据的速度比操作系统、网络适配器或其他东西处理数据的速度快。但是我如何检查并防止它发生呢?如果我减少每次使用sc.write()的消息长度,然后增加重复次数,我仍然会遇到同样的问题。这似乎只是短时间内数据量的问题。我也没有看到sc.write()抛出任何异常(我知道在上面的示例中我没有检查,但在测试中有)JavaNIO:发送大消息会很快导致数据包被截断和数据丢失,java,networking,network-programming,nio,Java,Networking,Network Programming,Nio,我遇到了一个棘手的问题,从Java(NIO)服务器(运行Linux)快速连续地向客户机发送多条大型消息会导致数据包被截断。消息必须很大且发送速度非常快,才能发生问题。下面是我的代码所做的基本内容(不是实际的代码,而是或多或少发生的事情): 存在数据丢失,并且分组开始一起运行,使得分组5的开始(在本例中)到达与分组4的开始相同的消息中。它不仅仅是截断,而是将消息一起运行 我认为这与TCP缓冲区或“窗口大小”有关,或者这里的服务器提供数据的速度比操作系统、网络适配器或其他东西处理数据的速度快。但是我
如果我能以编程方式检查它是否还没有准备好接收更多数据,并进行延迟,然后等待它准备好,我会很高兴。我也不确定“sc.socket().setSendBufferSize(1024*1024);”是否有任何效果,或者我是否需要在Linux方面对此进行调整。有没有办法真正“冲洗”出袜子通道?作为一种蹩脚的解决方法,我可以在任何时候尝试发送超过10KB的消息时(在我的应用程序中并不经常),显式强制发送缓冲的任何内容。但我不知道有什么方法可以强制发送缓冲区(或者等到它发送了)。谢谢你的帮助 我没有做过任何NIO编程,但是根据Javadocs,如果SocketChannel处于非阻塞模式(就像您的一样),并且套接字的输出缓冲区已满,sc.write()将不会写入整个ByteBuffer 因为你写得太快了,很可能你的连接被淹没了,你的网络或接收者跟不上 如果我能通过编程检查它是否还没有准备好接收更多数据,我会很高兴
您需要检查sc.write()的返回值,以确定输出缓冲区是否已满。您没有检查以下内容的返回值:
sc.write(bb);
这将返回写入的字节数,可能少于缓冲区中可用的数据。由于nio的工作方式,您可能只需在bytebuffer上调用remaining(),查看是否还有剩余数据。sc.write()不发送部分或全部数据的原因有很多。您必须检查返回值和/或缓冲区中剩余的字节数
for (int n=0; n<20; n++){
ByteBuffer bb = encoder.encode(CharBuffer.wrap(msg+'\0'));
if(sc.write(bb) > 0 && bb.remaining() == 0) {
// all data sent
} else {
// could not send all data.
}
bb.rewind();
}
for(int n=0;n 0&&bb.remaining()==0){
//发送的所有数据
}否则{
//无法发送所有数据。
}
bb.倒带();
}
不要假设您可以控制哪些数据最终会出现在哪个数据包中
更多信息:您正在使用非阻塞模式:sc.configureBlocking(false)
将blocking设置为true,代码应按原样工作。这里的其他人提出的检查发送计数和循环的建议也会起作用 是的!期望通过网络尽可能快地发送数据是不合理的。如果您没有阻塞,则需要测试写入的结果。似乎“sc.socket().setTcpNoDelay(true);”将有助于确保多条消息不会组合到单个数据包中。我对该方法调用不太熟悉,但需要帮助!=保证,这意味着我在上面的链接中解释的技术更谨慎。
sc.write(bb);
for (int n=0; n<20; n++){
ByteBuffer bb = encoder.encode(CharBuffer.wrap(msg+'\0'));
if(sc.write(bb) > 0 && bb.remaining() == 0) {
// all data sent
} else {
// could not send all data.
}
bb.rewind();
}