我使用Java NIO的SocketChannel来写:int n = socketChannel.write(byteBuffer);
大多数情况下,数据以一个或两个部分发送;即,如果数据不能在一个时隙中发送,则重试剩余的数据。
这里的问题是,有时,数据在一次尝试中没有完全发送,当尝试多次发送其余数据时,即使在尝试几次之后,也没有一个字符被写入通道,最后在一段时间之后发送剩余数据。此数据可能不大,大约为2000个字符。
造成这种行为的原因可能是什么?外部因素如RAM、操作系统等是否会造成阻碍?
请帮我解决这个问题。如果需要任何其他信息,请让我知道。谢谢
编辑:
在NIO SocketChannel中是否有方法在实际写入之前检查通道是否可以提供要写入的数据。这里的意图是,在尝试写入完整的数据之后,如果一些数据还没有写入通道,在写入剩余的数据之前,我们可以检查SocketChannel是否可以接受更多的数据;因此,负责写入该数据的线程可以等待或做其他事情,而不是徒劳地尝试多次。
2条答案
按热度按时间icnyk63a1#
TCP/IP是一种流协议。在任何级别上都不能保证您发送的数据不会被分解为单字节段,或者在您编写数据时不会被分解为单字节段和单字节段之间的任何数据。
你的期望是错的。
当套接字发送缓冲区填满时,重新编辑(
write(
)将返回零。当你得到它时,注册OP_WRITE
的通道并停止写循环。当你得到OP_WRITE
时,注销它(非常重要)并继续写。如果write()
再次返回零,则重复。v6ylcynt2#
在使用TCP时,我们只能在套接字缓冲区被填满之前写入发送方端的套接字通道,而不是在那之后。因此,如果接收方消耗数据的速度很慢,发送方端的套接字缓冲区就会填满,正如你提到的,write()可能会返回零。
在任何情况下,当发送端有一些数据要发送时,我们应该使用OP_WRITE作为感兴趣的操作向选择器注册SocketChannel,当选择器返回SelectionKey时,检查key.isWritable()并尝试在该通道上写入。正如上面Nilesh提到的,在写入完整数据后,不要忘记使用选择器取消注册OP_WRITE位。