java.net.SocketTimeoutException两类超时差异及timeout触发时机咨询
java.net.SocketTimeoutException: timeout 触发场景解析
先明确你遇到的两种SocketTimeoutException核心差异:
connect timed out:仅发生在TCP连接建立阶段,是客户端在设定的connectTimeout时间内无法和服务器建立连接导致的(比如服务器宕机、网络阻塞)。- 不带
connect前缀的timeout:发生在连接成功建立后的IO交互阶段,结合你提供的异常堆栈,主要触发场景如下:
1. 读取操作超时(核心场景)
这是最常见的触发原因,对应OkHttp配置的readTimeout参数。当客户端和服务器成功建立连接后,服务器在readTimeout设定的时间内没有返回任何数据(包括响应头、响应体、SSE的心跳/消息),客户端的读取操作就会超时,抛出这个异常。
从你的堆栈可以看到,异常发生在Http1ExchangeCodec.readHeaderLine环节,也就是客户端在等待服务器返回响应头时超出了读取超时时间。
2. SSE长连接的心跳/数据推送中断
SSE是基于HTTP的长连接,依赖服务器定期推送消息或心跳包维持连接。如果服务器因为负载过高、逻辑异常等原因,长时间没有推送任何数据,客户端的读取线程会一直阻塞等待,直到触发readTimeout,抛出该异常。
3. 底层Socket意外关闭后的超时触发
你的堆栈中包含Caused by: java.net.SocketException: Socket closed,说明Socket连接已经被关闭,但客户端的读取操作仍在阻塞等待数据。这种情况可能是:
- 服务器主动关闭了连接(比如连接空闲超时)
- 网络波动导致连接被动断开,但客户端未及时感知,直到读取操作超时
4. OkHttp的AsyncTimeout机制触发
OkHttp通过Okio的AsyncTimeout统一管理各类IO超时,当任何已建立连接后的IO操作(如读取、写入)超出了设定的超时阈值,就会抛出这种不带connect前缀的SocketTimeoutException: timeout,以此区分连接阶段的超时异常。
内容的提问来源于stack exchange,提问作者Sam Smith
相关产品推荐
相关产品推荐

