Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.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
Java 当消息大小较大时,socketchannel.write()会变得非常慢_Java_Nio_Socketchannel - Fatal编程技术网

Java 当消息大小较大时,socketchannel.write()会变得非常慢

Java 当消息大小较大时,socketchannel.write()会变得非常慢,java,nio,socketchannel,Java,Nio,Socketchannel,在我使用java nio的程序中,socketchannel.write()在尝试连续写入10 KB消息时变得非常慢。测得的写入完整10 KB消息的时间介于160 ms和200 ms之间。但写入完整5 KB消息的时间仅为0.8 ms 在选择器中,我只读取Selection.OP_,不处理Selection.OP_写入。当收到一条完整的大消息时,它会被写入另一个接收器4次 有人也有同样的问题吗?有一篇关于socketchannel.write()慢的帖子。我的问题是如何在读操作和写操作之间交替切换

在我使用java nio的程序中,socketchannel.write()在尝试连续写入10 KB消息时变得非常慢。测得的写入完整10 KB消息的时间介于160 ms和200 ms之间。但写入完整5 KB消息的时间仅为0.8 ms

在选择器中,我只读取Selection.OP_,不处理Selection.OP_写入。当收到一条完整的大消息时,它会被写入另一个接收器4次

有人也有同样的问题吗?有一篇关于socketchannel.write()慢的帖子。我的问题是如何在读操作和写操作之间交替切换

如果我添加一个惯性值,例如150毫秒,响应时间就会缩短。有没有办法找到缓冲区已满的时间,以便让程序等待。我的操作系统是windows xp

谢谢

我遵循EPJ的建议,检查写入的字节数。但响应时间仍然很长。我在这里发布了我的部分代码,并想检查我的代码是否有错误

//这是使用nio的writeData()部分:

      while (buffer.hasRemaining()) {   
        try {           
                buffer.flip();                  
                n = socket.write(buffer);           
                if(n == 0) {                
                    key.interestOps(SelectionKey.OP_WRITE);
                    key.attach(buffer);             
                    break;
                }                               
        } catch (IOException e) {               
            e.printStackTrace();
        } finally {
            buffer.compact();
        }
    }   

    if(buffer.position()==0) {                  
        key.interestOps(SelectionKey.OP_READ);
    }

如果写入时间超过20微秒,我建议您存在缓冲区已满问题。我假设您正在使用阻塞NIO。当发送缓冲区未满时,通常需要5-20微秒。在过去,我已经将我的服务器配置为杀死任何需要2ms写入的慢速消费者。(可能有点咄咄逼人。)

您可以尝试增加发送缓冲区的大小(Socket.setSendBufferSize(int),它也可用于SocketChannels),但似乎您正在尝试发送超出带宽允许的数据


10 KB不是一个大消息,典型的发送缓冲区大小是64 KB,因此要使其满,您需要有6-7条消息未发送。这可能解释了5KB的方式相对较快。

我建议您的读取过程较慢,这会导致其接收缓冲区备份,这会导致发送缓冲区备份,从而导致发送暂停

或者您没有为非阻塞模式正确编写代码。如果write()方法的结果为零,则必须(a)将interesttops更改为OP_write,并(b)返回select循环。当你得到OP_WRITE时,你必须重复写入;如果您写入了所有数据,请将数据更改回OP_READ,否则一切保持原样,等待下一次OP_写入。如果在非阻塞模式下写入时尝试循环,即使在存在零长度写入的情况下,也只会旋转,浪费CPU周期和时间

模错误:

while (buffer.position() > 0)
{
  try
  {
    buffer.flip();
    int count = ch.write(buffer);
    if (count == 0)
    {
      key.interestOps(SelectionKey.OP_WRITE);
      break;
    }
  }
  finally
  {
    buffer.compact();
  }
}
if (buffer.position() == 0)
{
  key.interestOps(SelectionKey.OP_READ);
}

我猜它一直试图发送一个10KB的TCP数据包,但失败了很多。消息是连续发布的。拓扑是一个节点链。消息间隔为100ms@MartijnCourteaux不是。TCP打包发生在较低级别。它不会尝试发送IP数据包>路径MTU。谢谢。但我使用的是Java非阻塞套接字。当服务器收到消息时,它会将消息转发到下一个跃点4次。我不会将选择键更改为OP_WRITE。当我写入时,选择键为OP_READ。我想我的问题是tcp缓冲区已满。如果我的猜测是正确的,如何解决这个问题?关闭socketchannel会有帮助吗?确定为什么没有足够的带宽或使用速度慢,并修复它会有帮助。如果您无法控制其中任何一个,那么关闭插座是最后的手段。顺便说一句:如果您使用的是非阻塞,它不应该在写入时阻塞,它应该只是无法写入任何数据@苏珊,你正在做一个全新的注册。我说要把兴趣点改成OP_WRITE,我还说当你写成功的时候要把它们改回OP_READ。你没有那样做。另一个问题是,无论写入状态如何,都应该在flip()和write()之后压缩(),否则缓冲区将处于无效状态。另一个是write()永远不会返回<0:请参阅Javadoc。如果有一些示例代码,它将非常有用。更改windows系统tcp缓冲区是否有帮助?@susan请参见上文。众所周知,Windows socket发送和接收缓冲区在8k时太小,将它们增加到32k或48k总是有帮助的。不过,我相信您有一个编码问题,它无法解决。谢谢。我感谢你的帮助。我被困在这里有一段时间了,所以我很担心。你知道如何增加windows套接字缓冲区大小吗?我将继续修复我的编码问题。在消息之间添加间隔是一种解决方案,但是,它可能不是一个好的解决方案。@susan将键更改为OP_WRITE会影响select()的功能,但与实际写入无关。同上OP_READ和reading。如果您没有写出消息,那是因为您没有正确地围绕写操作循环,或者您没有正确地处理零长度写操作。我发布的代码应该能正确完成这两件事。您的Buffer.haslaining()测试不正确。这仅在读取时有效,或在缓冲区处于翻转状态时写入时有效。