setSoTimeout仅作用于Socket输入流的阻塞读操作,单位毫秒,需在connect后设置;超时抛SocketTimeoutException,写操作和连接建立不受影响。

通过 Socket 的 setSoTimeout 方法可以设置网络读操作(如 InputStream.read())的阻塞超时时间,避免线程无限等待远端响应。
setSoTimeout 的作用和生效范围
该参数仅影响基于 Socket 的输入流(getInputStream())上阻塞式读取操作,例如 read()、readLine()、readFully() 等。它不会影响连接建立(connect())、写入(write())或关闭操作。
超时单位为毫秒,设为 0 表示永不超时(默认行为);设为正整数(如 5000)表示最多等待对应毫秒,超时后抛出 SocketTimeoutException(是 IOException 的子类)。
正确设置时机
必须在调用 connect() 之后、执行任何读操作之前设置,否则可能无效(部分 JDK 实现下,未连接的 Socket 调用 setSoTimeout 会抛出 SocketException)。
- ✅ 推荐写法:先
socket.connect(addr, timeout),再socket.setSoTimeout(5000) - ❌ 错误写法:创建 Socket 后立即 setSoTimeout,此时 socket 尚未连接
- ⚠️ 注意:如果使用带地址的构造函数(如
new Socket(host, port)),内部已隐式完成连接,此时可直接 setSoTimeout
配合输入流使用的典型场景
设置后,所有后续阻塞读操作都会受其约束。捕获 SocketTimeoutException 即可区分“超时”与“连接断开/对端关闭”等其他异常:
-
SocketTimeoutException→ 远端未及时发数据,但连接仍可能有效,可重试或继续等待 -
IOException(非超时)→ 如连接重置、远程关闭、网络中断,通常需关闭 socket 并重建
示例片段:
Socket socket = new Socket();
socket.connect(new InetSocketAddress("example.com", 80), 3000);
socket.setSoTimeout(5000); // 读超时 5 秒
InputStream in = socket.getInputStream();
try {
int b = in.read(); // 此处最多阻塞 5 秒
} catch (SocketTimeoutException e) {
System.out.println("读取超时,但连接可能还活着");
} catch (IOException e) {
System.out.println("连接异常,建议关闭 socket");
}
常见误区提醒
- 不是全局配置:每个 Socket 实例独立维护自己的 soTimeout 值
- 不控制 write 行为:写满发送缓冲区时
write()可能阻塞,但不受 soTimeout 影响(可用setSendBufferSize和非阻塞 I/O 配合优化) - HTTP 客户端慎用:若使用
HttpURLConnection或 OkHttp,它们有自己的超时机制,不应直接操作底层 socket 的 soTimeout

















