很多时候在断网的时候, 一个http请求会以一个UnknownHostException结束
一个最原始的处理方法是把exception的msg以toast的形式抛出, 我经常这样干, 我觉得这样挺好的, 什么问题都一目了然
可是这样做的话, 99.999%的概率在用户反馈群中会有人报告”app报错了/弹出了乱码”, 然后不明所以的项目经理也会问这是发生了什么错误
所以还是要处理成错误页面, or即使是弹吐司, 也要弹一个不明所以的“网络错误”

UnknownHostException是什么呢, 它的文档说:

Thrown to indicate that the IP address of a host could not be determined.

所以它其实是整个请求的第一步: 域名解析, 出了错误

如果我们使用Java中最原始的的URL类来发出http请求, 如下:

URL url = new URL("http://www.google.com");
URLConnection conn = url.openConnection();
InputStream in = conn.getInputStream();

这个错误的发生的其中一个路径是(在System.getSeurityManager()有值的情况下):

URLConnection.getInputStream()
URLConnection.URLtoSocketPermission(URL)
URLConnection.getHostAndPort(URL)
InetAddress.getByName(String host)
...一堆内部impl调用
native Inet6AddressImpl.lookupAllHostAddr(String host) // 如果机器支持ipv6的话

如果sm为null的话

URLConnection.getInputStream()
URLConnection.getInputStream0()
URLConnection.connect()
plainConnect
plainConnect0
getNewHttpClient
new HttpClient()
HttpClient.openServer
NetworkClient.doConnect
new InetSocketAddress
InetAddress.getByName

native部分的代码在Inet6AddressImpl.c的Java_java_net_Inet6AddressImpl_lookupAllHostAddr函数中, 略过其中不知道在干什么的c层的东西, 它最主要做的是:

error = getaddrinfo(hostname, NULL, &hints, &res);

if (error) {
  NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
}

其中getaddrinfo是c中获取ip地址的函数

 The getaddrinfo() function is used to get a list of IP addresses and port
 numbers for host hostname and service servname.

NET_ThrowUnknownHostExceptionWithGaiError是定义在net_util_md.c中的一个函数, 基本上就是

jobject x = JNU_NewObjectByName(env, "java/net/UnknownHostException", "(Ljava/lang/String;)V", s);
if (x != NULL) (*env)->Throw(env, x);

所以就是这样了~