2

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

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

有没有会计同样的问题?有一篇关于 socketchannel.write() 慢的帖子。我的问题是如何在 OP_READ 和 OP_WRITE 之间交替更改?

如果我添加一个 inerval,例如 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);
    }
4

2 回答 2

3

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

否则你没有为非阻塞模式正确编写代码。如果您从 write() 方法得到零结果,您必须 (a) 将 interestOps 更改为 OP_WRITE 并 (b) 返回您的选择循环。当您获得 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);
}
于 2011-11-08T00:34:29.460 回答
2

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

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

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

于 2011-11-07T21:42:07.693 回答