Java通过Socket InputStream读取文件时while循环阻塞无法退出是什么原因
循环无法退出的原因及解决方案
Socket.getInputStream() 返回的输入流的 read(byte[]) 方法是阻塞调用,只有以下三种情况会触发返回:
- 成功读取到至少1字节数据,返回本次读取到的字节数
- 对端正常关闭连接,返回
-1 - 连接出现IO异常,抛出对应错误
你的代码卡在(count = in.read(buffer))调用上,是因为当前既没有新数据传输,也没有收到对端的连接关闭通知,read方法会一直挂起等待,既不会进入循环体打印次数,也不会返回-1退出循环。
常见触发场景
- 发送端传输完文件后没有主动关闭Socket连接,连接保持在半开状态,没有发送FIN包通知接收端传输结束
- 网络中断、防火墙丢包等问题导致对端的关闭通知无法到达接收端,接收端感知不到连接已断开
- 若使用HTTP等带长连接机制的协议,服务端发送完数据后会复用连接不主动关闭,也会导致read一直阻塞
代码潜在问题
你当前的文件写入逻辑存在错误,fos.write(buffer) 会把整个16KB的缓冲区全部写入文件,但最后一次读取大概率读不满16KB,会导致最终文件末尾残留上一次缓冲区的无效内容,需要修改为:
fos.write(buffer, 0, count);
仅写入本次实际读取到的字节数。
解决方案
- 给Socket设置读取超时:调用
socket.setSoTimeout(5000)(单位为毫秒,可根据实际场景调整),如果超过指定时间没有读到数据会抛出SocketTimeoutException,捕获异常后即可终止循环 - 按应用层协议约定控制读取长度:比如传输文件前先发送4字节的文件总长度,接收端累计读到总长度后主动调用break退出循环,不需要等待对端关闭连接
- 要求发送端传输完成后主动调用
Socket.close()或者Socket.shutdownOutput()方法,通知接收端传输结束,此时read会返回-1,循环正常退出
内容的提问来源于stack exchange,提问作者Ziv Sion
相关产品推荐
相关产品推荐

