java - 当消息大小很大时,socketchannel.write() 会变得非常慢

标签 java nio socketchannel

在我使用 java nio 的程序中,当尝试连续写入 10 KB 消息时,socketchannel.write() 变得非常慢。写入完整 10 KB 消息的测量时间在 160 毫秒到 200 毫秒之间。但写入完整的 5 KB 消息只需要 0.8 毫秒。

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

有人有同样的问题吗?有一篇关于 socketchannel.write() 慢的文章。我的问题是如何在 OP_READ 和 OP_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);
    }

最佳答案

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

或者您没有正确编写非阻塞模式的代码。如果从 write() 方法得到零结果,则必须 (a) 将interestOps 更改为 OP_WRITE 并 (b) 返回到 select 循环。当你得到 OP_WRITE 时,你必须重复写入;如果您写入了所有数据,请将interestOps更改回OP_READ,否则保留所有内容并等待下一个OP_WRITE。如果您尝试在非阻塞模式下写入时循环,即使存在零长度写入,您也只会旋转,浪费 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);
}

关于java - 当消息大小很大时,socketchannel.write() 会变得非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8042212/

相关文章:

java - 是否可以像在 android 中一样为我的应用程序的 Activity 创建一个最近的屏幕

java - 是否调用new Object();两次使第一次调用创建的对象符合垃圾回收条件?

java - 使用 NIO 的套接字中客户端的 IP 地址

java nio socketChannel 读取总是返回相同的数据

Java SocketChannel 没有检测到断开连接?

java - 我们如何使 ExtractMpegFramesTest 中的 saveFrame() 方法更高效?

java - Mysql和java socket并行压力测试

java - 我可以在 Firefox 和 Chrome 中使用以下代码上传图像,但 Edge 中出现错误 :

java - 是否可以将 Process stdout InputStream 读取到 NIO ByteBuffer 中?

java - 如何从 TCP 套接字获取数据到 ByteBuffer