当前位置:  开发笔记 > 编程语言 > 正文

Java NIO:快速发送大量消息会导致数据包被截断和数据丢失

如何解决《JavaNIO:快速发送大量消息会导致数据包被截断和数据丢失》经验,为你挑选了2个好方法。

我有一个令人讨厌的问题,即从Java(NIO)服务器(运行Linux)快速连续发送多个大型消息到客户端将导致截断的数据包.消息必须很大并且发送速度非常快以便发生问题.这基本上就是我的代码所做的事情(不是实际代码,而是或多或少正在发生的事情):

//-- setup stuff: --
Charset charset = Charset.forName("UTF-8");
CharsetEncoder encoder = charset.newEncoder();
String msg = "A very long message (let's say 20KB)...";

//-- inside loop to handle incoming connections: --
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.socket().setTcpNoDelay(true);
sc.socket().setSendBufferSize(1024*1024);

//-- later, actual sending of messages: --
for (int n=0; n<20; n++){
  ByteBuffer bb = encoder.encode(CharBuffer.wrap(msg+'\0'));
  sc.write(bb);
  bb.rewind();
}

因此,如果数据包足够长并尽可能快地发送(即在这样的循环中没有延迟),那么在另一端它经常会出现这样的情况:

[COMPLETE PACKET 1]
[COMPLETE PACKET 2]
[COMPLETE PACKET 3]
[START OF PACKET 4][SOME OR ALL OF PACKET 5]

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

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

如果我能以编程方式检查它是否还没有准备好接收更多数据,并且延迟,并等待它准备就绪,我会很高兴.我也不确定"sc.socket().setSendBufferSize(1024*1024);" 有任何影响,或者如果我需要在Linux方面调整这一点.有没有办法真正"刷新"SocketChannel?作为一种蹩脚的解决方法,我可以尝试在我尝试发送超过10KB的消息时,明确强制完全发送任何缓冲的内容(这在我的应用程序中并不常见).但我不知道有什么方法可以强制发送缓冲区(或者等到它发送完毕).谢谢你的帮助!



1> 小智..:

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();
}



2> wds..:

您没有检查返回值:

sc.write(bb);

这将返回写入的字节数,该字节数可能小于缓冲区中可用的数据.由于nio如何工作,你可以在你的bytebuffer上调用remaining()以查看是否有任何剩余.

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有