在我使用java nio的程序中,socketchannel.write()在尝试连续写入10 KB消息时变得非常慢。写入完整10 KB消息的测量时间介于160 ms和200 ms之间。但是编写完整的5 KB消息的时间只需要0.8毫秒。
在选择器中,我只有Selection.OP_READ并且不处理Selection.OP_WRITE。当收到大的完整消息时,它会被写入另一个接收器4次。
有人遇到同样的问题吗?有关于socketchannel.write()的帖子很慢。我的问题是如何在OP_READ和OP_WRITE之间进行替换?
如果我添加一个例如150毫秒的inerval,则响应时间会减少。有什么方法可以找到缓冲区已满的时间,所以我可以让程序等待。我的操作系统是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);
}
答案 0 :(得分:3)
我建议您的阅读过程很慢,这会导致其接收缓冲区备份,这会导致您的发送缓冲区备份,从而导致您的发送停止。
否则您还没有为非阻塞模式正确编写代码。如果从write()方法得到零结果,则必须(a)将interestOps更改为OP_WRITE并(b)返回到select循环。当你得到OP_WRITE时,你必须重复写;如果您编写了所有数据,请将interestOps更改回OP_READ,否则保留所有内容并等待下一个OP_WRITE。如果你在非阻塞模式下写入时尝试循环,即使存在零长度写入,你也会旋转,浪费CPU周期和时间。
Modulo错误:
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);
}
答案 1 :(得分:2)
如果写入超过20微秒,我建议你有一个缓冲区问题。我假设您正在使用阻止NIO。当发送缓冲区未满时,通常需要5到20微秒。在过去,我已经配置我的服务器来杀死任何需要2毫秒写入的慢速消费者。 (可能有点咄咄逼人。;)
您可以尝试增加发送缓冲区的大小(Socket.setSendBufferSize(int),也可用于SocketChannels),但看起来您尝试发送的数据超出了带宽允许的范围。
10 KB不是一个大消息,典型的发送缓冲区大小是64 KB,因此要使其满,您需要有6-7个消息未发送。这可能解释了5KB相对较快的方式。