Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaNIO:发送大消息会很快导致数据包被截断和数据丢失_Java_Networking_Network Programming_Nio - Fatal编程技术网

JavaNIO:发送大消息会很快导致数据包被截断和数据丢失

JavaNIO:发送大消息会很快导致数据包被截断和数据丢失,java,networking,network-programming,nio,Java,Networking,Network Programming,Nio,我遇到了一个棘手的问题,从Java(NIO)服务器(运行Linux)快速连续地向客户机发送多条大型消息会导致数据包被截断。消息必须很大且发送速度非常快,才能发生问题。下面是我的代码所做的基本内容(不是实际的代码,而是或多或少发生的事情): 存在数据丢失,并且分组开始一起运行,使得分组5的开始(在本例中)到达与分组4的开始相同的消息中。它不仅仅是截断,而是将消息一起运行 我认为这与TCP缓冲区或“窗口大小”有关,或者这里的服务器提供数据的速度比操作系统、网络适配器或其他东西处理数据的速度快。但是我

我遇到了一个棘手的问题,从Java(NIO)服务器(运行Linux)快速连续地向客户机发送多条大型消息会导致数据包被截断。消息必须很大且发送速度非常快,才能发生问题。下面是我的代码所做的基本内容(不是实际的代码,而是或多或少发生的事情):

存在数据丢失,并且分组开始一起运行,使得分组5的开始(在本例中)到达与分组4的开始相同的消息中。它不仅仅是截断,而是将消息一起运行

我认为这与TCP缓冲区或“窗口大小”有关,或者这里的服务器提供数据的速度比操作系统、网络适配器或其他东西处理数据的速度快。但是我如何检查并防止它发生呢?如果我减少每次使用sc.write()的消息长度,然后增加重复次数,我仍然会遇到同样的问题。这似乎只是短时间内数据量的问题。我也没有看到sc.write()抛出任何异常(我知道在上面的示例中我没有检查,但在测试中有)


如果我能以编程方式检查它是否还没有准备好接收更多数据,并进行延迟,然后等待它准备好,我会很高兴。我也不确定“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();
}