HttpURLConnection.openConnection() 这个方法本身不会直接抛出异常,即使目标 URL 不可达或者网络有问题。这是因为 openConnection() 只是创建了一个到目标 URL 的连接对象,但并未实际建立连接。实际的网络连接过程(包括 DNS 解析、TCP 握手等)会在你首次试图读取或写入连接时发生。

如果在实际建立连接过程中发生错误,或者连接超时,你可能会看到如下几种异常:

  1. java.net.SocketTimeoutException:如果连接的读取或写入超时,将抛出此异常。你可以使用 setConnectTimeout(int timeout)setReadTimeout(int timeout) 分别设置连接超时和读取超时的时间。
  2. java.net.UnknownHostException:如果 URL 的主机名无法解析,将抛出此异常。
  3. java.net.ConnectException:如果无法建立到目标服务器的 TCP 连接,将抛出此异常。
  4. java.io.IOException:如果在读取或写入连接时发生其他网络错误,将抛出此异常。
  5. java.net.ProtocolException:如果HTTP协议出现问题,如HTTP方法的名字是错误的。

因此,确保代码正确处理了以上异常,以避免在网络问题发生时程序崩溃。

另外,一般来说,如果你试图打开一个网络连接,Java 库在下面的顺序进行操作:

  1. 解析主机名:Java 首先需要找到主机名对应的 IP 地址。这是通过 DNS 查询来完成的。如果 DNS 查询失败(例如,主机名不存在或 DNS 服务器无响应),将抛出 java.net.UnknownHostException
  2. 建立 TCP 连接:一旦主机名被解析为 IP 地址,Java 尝试与服务器建立 TCP 连接。如果这个过程失败(例如,服务器没有响应,或者网络不可达),将抛出 java.net.ConnectException
  3. 发送 HTTP 请求:TCP 连接建立后,Java 发送 HTTP 请求到服务器。如果请求不能被正确发送(例如,由于网络问题或者服务器突然关闭连接),将抛出 java.io.IOException
  4. 接收 HTTP 响应:接收到服务器的 HTTP 响应后,如果响应不能被正确接收或解析,将抛出 java.io.IOExceptionjava.net.ProtocolException
  5. 读取或写入超时:在上述过程中,如果在设定的超时时间内没有完成,将抛出 java.net.SocketTimeoutException

所以,在一般情况下,异常抛出的顺序是 UnknownHostException -> ConnectException -> IOException/ProtocolException -> SocketTimeoutException。当然,这取决于具体情况,不一定总是这样。

也就是说即使设置了setConnectTimeout超时时间,但有可能在设置的超时时间之前会先抛出UnknownHostException ,ConnectException ,IOException/ProtocolException

setConnectTimeout(int timeout) 是设置连接超时时间,即在建立网络连接(包括 DNS 解析和 TCP 握手)的过程中,如果超过了这个时间,就会抛出 java.net.SocketTimeoutException

然而,在尝试建立网络连接之前,就可能会出现 UnknownHostException(如果主机名无法解析)和 ConnectException(如果无法建立 TCP 连接)。这些异常可能会在连接超时之前就发生。

此外,即使网络连接被成功建立,IOExceptionProtocolException 也可能在后续的数据传输过程中发生。例如,如果服务器意外关闭了连接,或者服务器发送的 HTTP 响应无法被正确解析。

因此,虽然你设置了连接超时时间,但是你的代码还需要能够处理这些其他的网络异常,以确保程序的稳定性。

Last modification:June 6, 2023
If you think my article is useful to you, please feel free to appreciate