我正在用 Java 進行套接字編程,但我setSoTimeout()對它的例外感到困惑。
我Callable<String>在服務器端有一個簡單的接受連接的方法:
private Callable<String> waitForConnectionCallable = new Callable<String>() {
@Override
public String call() throws IOException {
if (socket == null) {
socket = new ServerSocket(PORT);
}
socket.setSoTimeout(CONNECTION_TIMEOUT);
Socket inSocket = socket.accept();
return "CONNECTED";
}
};
我以這種方式呼叫和處理它:
try {
Future<String> connectionFuture = executorService.submit(waitForConnectionCallable);
String connectionResult = connectionFuture.get();
} catch (ExecutionException | InterruptedException e) {
Logs.error(TAG, "No connection received");
e.printStackTrace();
}
現在,java 檔案setSoTimeout()提到了引發SocketTimeoutException,但奇怪的是它沒有包含在 Throws 串列中:
使用指定的超時時間(以毫秒為單位)啟用/禁用 SO_TIMEOUT。將此選項設定為正超時值后,對此 ServerSocket 的 accept() 呼叫將僅阻塞這段時間。如果超時到期,則會引發 java.net.SocketTimeoutException,但 ServerSocket 仍然有效。零超時被解釋為無限超時。該選項必須在進入阻止操作之前啟用才能生效。
引數:超時——指定的超時時間,以毫秒為單位
拋出: SocketException – 如果底層協議存在錯誤,例如 TCP 錯誤 IllegalArgumentException – 如果超時為負
當我運行程式并且連接超時時,我在 catch 塊中得到了 SocketTimeoutException,但以這種方式:
java.util.concurrent.ExecutionException: java.net.SocketTimeoutException: Accept timed out
我的問題是,我怎樣才能捕捉到那個特定的例外?我無法將它添加到我的呼叫者的 catch 陳述句中,因為我得到了它沒有在方法中拋出的編譯錯誤。此外,我無法添加到該call()方法(在 Callable 中),因為IOException,一個更一般的例外已經存在。
另外:為什么 SocketTimeoutException 不是setSoTimeout()簽名的一部分?考慮到它不是 SocketException 的子類。
uj5u.com熱心網友回復:
在你的觀察中,有幾件事需要糾正
現在,setSoTimeout() 的 java 檔案提到了引發 SocketTimeoutException,但奇怪的是它沒有包含在 Throws 串列中
不,它說
使用指定的超時時間(以毫秒為單位)啟用/禁用 SO_TIMEOUT。將此選項設定為非零超時,對此 ServerSocket 的 accept() 呼叫將僅阻塞這段時間。如果超時到期,則會引發 java.net.SocketTimeoutException,但 ServerSocket 仍然有效。該選項必須在進入阻止操作之前啟用才能生效。超時必須 > 0。超時為零被解釋為無限超時。
這意味著,如果您使用 設定超時setSoTimeout(),SocketTimeoutException則將拋出 a,如果在接受連接時發生超時。SoSocketTimeoutException不是由 拋出setSoTimeout(),因此它不在其拋出串列中。
您可以在accept()方法中捕獲超時例外。IOException如果在接受連接時出現問題,它會拋出一個。超時可能是原因之一。
像下面這樣:
private Callable<String> waitForConnectionCallable = new Callable<String>() {
@Override
public String call() throws IOException {
if (socket == null) {
socket = new ServerSocket(PORT);
}
socket.setSoTimeout(CONNECTION_TIMEOUT);
try {
Socket inSocket = socket.accept();
} catch (SocketTimeoutException e) {
// do timeout handling...
return "TIMEOUT";
}
return "CONNECTED";
}
};
uj5u.com熱心網友回復:
您正在混合一些東西: SocketTimeoutException由socket.accept(). socket.setSoTimeout()可以拋出一個IOException(雖然很少)。
當SocketTimeoutException被拋出到您的call()方法(by socket.accept())中時,它將被包裝在一個 中ExecutionException,這是一個包裝例外。然后,您可以通過相應地呼叫e.getCause()和處理來訪問原始例外。
編輯 - 我會在您的代碼中對例外處理進行一些更改。首先,我將使用 aCallable<Socket>而不是,Callable<String>以便您稍后可以輕松使用套接字,因為您確定它已打開并已連接:
private Callable<Socket> waitForConnectionCallable = new Callable<>() {
@Override
public Socket call() throws IOException {
if (socket == null) {
socket = new ServerSocket(PORT);
socket.setSoTimeout(CONNECTION_TIMEOUT);
}
return socket.accept(); // Can throw IOException or SocketTimeoutException
}
};
然后,在 中執行例外處理waitForConnectionCallable.get():
try {
Future<String> connectionFuture = executorService.submit(waitForConnectionCallable);
String connectionResult = connectionFuture.get();
} catch (InterruptedException e) {
Thread.interrupted();
} catch (ExecutionException e) { // IOException or SocketTimeoutException
Throwable cause = e.getCause();
t.printStackTrace();
if (t instanceof SocketTimeoutException) {
Logs.error(TAG, "No connection received");
} else { // IOException
Logs.error(TAG, "Error waiting for connection: " t.getMessage());
}
}
或者,您可以在 中執行等待Callable,但是設定套接字超時可能沒有意義,因為您已經在使用不同的執行緒,因此您可以保持阻塞模式:
private Callable<Socket> waitForConnectionCallable = new Callable<>() {
@Override
public Socket call() throws IOException {
if (socket == null) {
socket = new ServerSocket(PORT);
socket.setSoTimeout(CONNECTION_TIMEOUT);
}
for (;;) { // Until we receive a connection
try {
return socket.accept(); // Can throw IOException or SocketTimeoutException
} catch (SocketTimeoutException e) {
// Do something? return null, log, continue, ...
} // IOException is not caught here and will bubble up in the ExecutionException
}
}
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/328759.html
