当前位置:  开发笔记 > 编程语言 > 正文

java socket/output stream写道:它们阻塞了吗?

如何解决《javasocket/outputstream写道:它们阻塞了吗?》经验,为你挑选了2个好方法。

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

对我来说写一个写入可能会阻塞是没有意义的.



1> Stephen C..:

对Socket的写入也可以阻塞,特别是如果它是TCP套接字.操作系统仅缓冲一定量的未传输(或传输但未确认)数据.如果您写的东西比远程应用程序能够读取的速度快,那么套接字最终会备份并且您的write调用将被阻止.

回答这些后续问题:

那么有没有为此设置超时的机制?我不确定它有什么行为......如果缓冲区已满,可能会丢弃数据?或者可能删除缓冲区中的旧数据?

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

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

相反,如果使用UDP套接字,则write()呼叫不会在任何相当长的时间内阻塞.但缺点是,如果存在网络问题或者远程应用程序没有跟上,消息将被丢弃,而不会向任何一端发出通知.此外,您可能会发现消息有时会无序传递到远程应用程序.由您(开发人员)来处理这些问题.

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



2> Noel Grandin..:

唯一的方法是使用NIO和选择器.

请参阅此错误报告中的Sun/Oracle工程师的文章:http://bugs.sun.com/bugdatabase/view_bug.do?video_id = 4031100

推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有