開發者在 Android 中呼叫 socket.setSoTimeout(200) 設定讀取超時 200ms,但實際運行中超時設定不生效,連線長時間阻塞不釋放。
setSoTimeout(int timeout) 設定的是讀取操作(InputStream.read())的超時時間,單位為毫秒。200ms 即 0.2 秒。若連線建立階段(connect())或寫入操作阻塞,setSoTimeout 不會生效。
setSoTimeout 控制連線建立超時 → 應用 Socket.connect(endpoint, timeout) 或 Socket(SocketAddress, timeout) 建構子。SocketChannel 配合 Selector。| 階段 | 方法 | 說明 |
|---|---|---|
| 連線建立 | socket.connect(socketAddress, timeoutMs) | 阻塞直到連線成功或超時拋出 SocketTimeoutException |
| 讀取資料 | socket.setSoTimeout(timeoutMs) | 針對 InputStream.read(),超時拋出 SocketTimeoutException,連線保持開啟 |
| 寫入資料 | 無直接 API | 需使用 SocketChannel 非阻塞模式 + Selector 實作寫入超時邏輯 |
Socket socket = new Socket();
int connectTimeout = 3000; // 3秒連線超時
int readTimeout = 200; // 200ms讀取超時
try {
// 1. 連線階段超時
socket.connect(new InetSocketAddress(host, port), connectTimeout);
// 2. 讀取階段超時
socket.setSoTimeout(readTimeout);
InputStream in = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = in.read(buffer); // 若200ms無資料可讀,拋出SocketTimeoutException
} catch (SocketTimeoutException e) {
// 處理超時:連線超時或讀取超時
Log.e("Socket", "Timeout: " + e.getMessage());
} finally {
try { socket.close(); } catch (IOException ignored) {}
}
setSoTimeout(0) 表示無限等待(預設值)。setSoTimeout 僅控制讀取超時。連線超時需用 connect(address, timeout),寫入超時需自行實作非阻塞邏輯。釐清三者邊界,才能正確處理 Socket 超時場景。