socket.setsotimeout(int timeout)为读操作设毫秒级超时,超时抛sockettimeoutexception;仅作用于读取,不影响连接(需connect(timeout))和写入;须连接完成后、读取前设置;需捕获异常并合理处理。

调用 Socket.setSoTimeout(int timeout) 可以为 Socket 的读操作(如 InputStream.read()、BufferedReader.readLine() 等)设置超时时间,单位是毫秒。一旦读取数据在指定时间内未完成,就会抛出 java.net.SocketTimeoutException,从而避免线程无限阻塞,防止程序假死。
超时只作用于读操作,不影响连接和写入
这个设置仅控制从底层输入流中读取数据的等待时间,对以下操作无影响:
- 建立 TCP 连接(即
new Socket(host, port)或socket.connect())——需用connect(timeout)单独设连接超时 - 发送数据(
OutputStream.write())——写操作通常不阻塞(除非缓冲区满且 TCP 窗口关闭,但此时也不受setSoTimeout约束)
必须在建立连接后、读取前设置才生效
如果在连接尚未完成(比如还在三次握手阶段)就调用 setSoTimeout(),部分 JDK 实现可能忽略该设置;更关键的是,若在开始读取之后才设置,已发起的阻塞读不会被中断。正确顺序应为:
- 创建 Socket 实例(可传地址和端口,或先空参构造)
- 调用
connect()并完成连接(或使用带超时的 connect) - 立即调用
setSoTimeout(ms) - 再执行
getInputStream().read(...)等读操作
捕获 SocketTimeoutException 做合理处理
超时不是错误,而是预期中的控制机制。建议显式捕获并区分处理:
- 重试读取(适用于偶发网络延迟)
- 关闭连接并重连(适用于服务端响应慢或临时不可达)
- 返回默认值或降级逻辑(如 UI 展示“加载中…”超时后显示“暂无数据”)
- 记录日志但不打印完整堆栈(避免日志刷屏)
示例片段:
try {socket.setSoTimeout(5000); // 5秒超时
int b = socket.getInputStream().read(); // 可能抛出 SocketTimeoutException
} catch (SocketTimeoutException e) {
// 超时,做业务层面恢复
} catch (IOException e) {
// 其他 I/O 异常,如连接断开、reset 等
}
注意平台与 JDK 版本的兼容性细节
绝大多数场景下行为一致,但需留意:
- Linux/Windows/macOS 上均支持,但某些嵌入式或旧版 Android(API setSoTimeout 的实现可能不严格
- JDK 8+ 中,若 Socket 已关闭,再调用
setSoTimeout()会抛SocketException("Socket is closed") - 超时时间为 0 表示永不超时(即阻塞到底),负数会抛
IllegalArgumentException










