4.2 阻塞和超时
Socket的I/O调用可能会因为多种原因而阻塞。数据输入方法read()和receive()在没有数据可读时会阻塞。TCP套接字的write()方法在没有足够的空间缓存传输的数据时可能阻塞。ServerSocket的accept()方法和Socket的构造函数都会阻塞等待,直到连接建立(见第6.4节)。同时,长的信息往返时间,高错误率的连接和慢速的(或已发生故障的)服务器,都可能导致需要很长的时间来建立连接。所有这些情况,只有在连接请求得到满足后这些方法才会返回。当然,调用一个已经阻塞的方法将使应用程序停止(并使运行它的线程无效)。
当程序在等待一次调用的完成时如果还有其他任务要执行的情况会怎样(如,更新“忙碌”状态的光标或响应用户请求)?这些程序可能没有时间来等待一个阻塞的方法调用。那UDP数据报文丢失的情况呢?如果我们阻塞等待接收一个数据报文,而它已经丢失,则会导致程序无限期地阻塞下去。这里,我们将对各种阻塞方法和限制阻塞的途径进行探讨。在第5章,我们将接触到NIO包中的更加强大的非阻塞工具。
4.2.1 accept()、read()和receive()
对于这些方法,我们可以使用Socket类、ServerSocket类和DatagramSocket类的setSoTimeout()方法,设置其阻塞的最长时间(以毫秒为单位)。如果在指定时间内这些方法没有返回,则将抛出一个InterruptedIOException异常。对于Socket实例,在调用read()方法前,我们还可以使用该套接字的InputStream的available()方法来检测是否有可读的数据。