java套接字/输出流写入:它们是否阻止?

java套接字/输出流写入:它们是否阻止?,java,sockets,stream,Java,Sockets,Stream,如果我只向输出流上的套接字写入数据,它会阻塞吗?只有读取才能阻止,对吗?有人告诉我写操作可以阻止,但我只看到套接字读取方法的超时功能-socket.setSoTimeout() 写操作会阻塞对我来说没有意义。套接字上的写操作也会阻塞,特别是如果它是TCP套接字。操作系统将只缓冲一定数量的未传输(或已传输但未确认)数据。如果你写东西的速度快于远程应用程序的读取速度,那么套接字最终将备份,你的写调用将被阻塞 回答以下问题: 那么,是否有一种机制来设定 这个暂停?我不知道是什么 它会有……也许会扔掉

如果我只向输出流上的套接字写入数据,它会阻塞吗?只有读取才能阻止,对吗?有人告诉我写操作可以阻止,但我只看到套接字读取方法的超时功能-
socket.setSoTimeout()


写操作会阻塞对我来说没有意义。

套接字上的写操作也会阻塞,特别是如果它是TCP套接字。操作系统将只缓冲一定数量的未传输(或已传输但未确认)数据。如果你写东西的速度快于远程应用程序的读取速度,那么套接字最终将备份,你的
调用将被阻塞

回答以下问题:

那么,是否有一种机制来设定 这个暂停?我不知道是什么 它会有……也许会扔掉 缓冲区是否已满?或者可能 是否删除缓冲区中较旧的数据

没有在java.net.Socket上设置写入超时的机制。有一个
Socket.setSortimeout()
方法,但它会影响
accept()
read()
调用。。。而不是
write()
调用。显然,如果使用NIO、非阻塞模式和选择器,您可以获得写入超时,但这并不像您想象的那么有用

除非连接关闭,否则正确实现的TCP堆栈不会丢弃缓冲数据。但是,当您获得写入超时时,不确定另一端是否已接收到操作系统级缓冲区中当前的数据。。。或者不是。另一个问题是,您不知道上次写入的
数据中有多少实际传输到了操作系统级TCP堆栈缓冲区。由于缺少一些用于重新同步流*的应用程序级协议,在
写入操作超时后,唯一安全的做法是关闭连接

相比之下,如果您使用UDP套接字,
write()
调用将不会阻塞很长时间。但缺点是,如果出现网络问题或远程应用程序无法正常运行,消息将被丢弃在地板上,而不会通知任何一端。此外,您可能会发现消息有时会无序地传递到远程应用程序。这将由您(开发人员)来处理这些问题


*理论上可以做到这一点,但对于大多数应用程序来说,在已经可靠(到某一点)的TCP/IP流之上实现额外的重新同步机制是没有意义的。如果它真的有意义,你还需要处理连接关闭的可能性。。。因此,假设它已关闭会更简单。

实现这一点的唯一方法是使用NIO和选择器

请参阅此错误报告中Sun/Oracle工程师的书面报告:

没有超时功能这一事实本身并不表明它没有阻塞。有一个迹象表明它没有返回值:如果它没有阻塞,为什么不返回实际写入的字节数?另一个迹象是仅仅尝试一下。