我正在使用 Java NIO 的 SocketChannel 来编写:
int n = socketChannel.write(byteBuffer);
大多数时候数据是分一两部分发送的;即,如果一次尝试无法发送数据,则会重试剩余的数据。
这里的问题是,有时候,一次尝试没有发送完全数据,当尝试多次发送剩余数据时,会出现即使尝试多次,也没有一个字符被写入通道,最后一段时间后,剩余数据被发送。这个数据可能不会很大,大概有2000个字符。
造成这种行为的原因是什么? RAM、操作系统等外部因素会造成阻碍吗?
请帮我解决这个问题。如果需要任何其他信息,请告诉我。 谢谢
编辑:
NIO SocketChannel 中有没有一种方法可以在实际写入之前检查通道是否可以提供要写入的数据。这里的目的是,在尝试写入完整的数据后,如果某些数据尚未写入通道,则在写入剩余数据之前,我们可以检查SocketChannel是否可以接收更多数据;因此,负责写入此数据的线程可以等待或执行其他操作,而不是多次尝试而无果而终。
TCP/IP 是一种流式传输协议。在任何级别的任何地方,都不能保证您发送的数据不会被分解为单字节段,或介于该段和您编写的单个段之间的任何内容。
您的期望是错误的。
重新编辑,
write(
)当套接字发送缓冲区填满时将返回零。当您得到该信息时,注册 OP_WRITE
的通道并停止写入循环。当你得到OP_WRITE
时,注销它(非常重要)并继续写作。如果 write()
再次返回零,则重复。
使用 TCP 时,我们只能在套接字缓冲区填满之前写入发送方套接字通道,而不能在填满之后写入。因此,如果接收方消耗数据的速度很慢,发送方套接字缓冲区就会填满,正如您所提到的, write() 可能会返回零。
无论如何,当发送方有一些数据要发送时,我们应该向选择器注册 SocketChannel,并将 OP_WRITE 作为感兴趣的操作,当选择器返回 SelectionKey 时,检查 key.isWritable() 并尝试在其上写入渠道。正如 Nilesh 上面提到的,在写入完整数据后,不要忘记使用选择器取消注册 OP_WRITE 位。