前言

最近工作没有前段时间那么忙碌了,我翻了翻自己有道云笔记记录的最近一段时间解决的一些工作上的问题,还是蛮多的,所以想着抽几个知识点来梳理成Blog吧。

概述

IP现在是个很重要的东西,现在只要跟互联网相关的东西基本都是构建在IP网络之上的,IP 数据包几乎可以承载任何数据。在Android平台上,一般发起网络请求,都会使用Http协议,可能使用的库不同,比如会有最基本的 HttpUrlConnection,当然据我所知,现在网络请求的话,Okhttp会用得更多一些,关于Okhttp我也研究了一下它的实现,下次有机会写篇Blog啰嗦下。回到主题,这些库的实现会有区别,它们在应用层的处理策略会有差别,但是在应用层之后,根据网络分层(这里我们不考虑硬件的东西),Tcp –>Ip层的传输,所有的数据包都会以Ip数据包的形式在网络中传输。

Android中的Ip获取

Android应用层的处理

Android应用层一般只能通过封装API来获取到系统的IP地址,实现方式都比较典型,举个例子,如下:

public String getLocalIpAddress()  
    {  
        try  
        {  
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();)  
            {  
               NetworkInterface intf = en.nextElement();  
               for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();)  
               {  
                   InetAddress inetAddress = enumIpAddr.nextElement();  
                   if (!inetAddress.isLoopbackAddress())  
                   {  
                       return inetAddress.getHostAddress().toString();  
                   }  
               }  
           }  
        }  
        catch (SocketException ex)  
        {  
        }  
        return null;  
    }

如上是通过了Java API来获取到Ip地址的,Android同样提供了API来供应用开发者获取,这一部分的实现主要是ConnectivityManager中的。

主要代码如下:

WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());
                return ipAddress

以上两种实现,主要区别在于,使用Java API获取的是,使用2G/3G/4G网络的IP地址,而使用WifiManager获取到的是WIFI环境下的IP地址。

应用层的IP获取大抵如此,接下来,来更深入一步的探讨Android中的IP获取。

Android系统的实现

无论是wifi环境下,还是在移动网络环境下,都需要了解下DHCP的实现,这是最根本的东西,接下来大体介绍下DHCP。

DHCP实现

这里我根据我自己的理解,感性地说下dhcp的实现,同时参考了网络上的一些文章。首先,我们来复盘下整个IP获取流程:

  • 存在在Android系统侧的dhcp客户端,首先它肯定是不知道自己的IP地址的,也就是说DHCP服务器的IP地址对于客户端来说是未知的,这时候dhcp客户端只有向地址255.255.255.255发送特定的广播信息。请求信息主要包含客户端的网卡MAC地址还有客户端的计算机名称。网络上每一台安装了TCP/IP协议的主机都会接收到这种广播信息,但只有DHCP服务器才会做出响应。
  • 上面的流程,dhcp服务器会对dhcp客户端的请求做出响应,换句话说,它从尚未出租的IP地址中挑选一个分配给DHCP客户端,向DHCP客户端发送一个包含出租的IP地址和其他设置的DHCP OFFER提供信息,这里因为是了解这整个流程,不用过分去关注那些协议中的名词,只需要知道这时候,dhcp服务器已经向dhcp客户端提供IP了。
  • 在dhcp客户端收到DHCP OFFER提供信息后,会以广播方式回答一个DHCP REQUEST请求信息,所有的DHCP服务器都会收到这个信息,该信息中包含它所选定的DHCP服务器和服务器提供的IP地址。这里会这么做,主要是因为,网络中可能不止存在一台dhcp服务器,所以,需要dhcp客户端选定服务器,并向网络中的各个服务器告知。
  • DHCP服务器收到DHCP客户端回答的DHCP REQUEST请求信息之后,它便向DHCP客户端发送一个包含它所提供的IP地址和其他设置的DHCP ACK确认信息,告诉DHCP客户端可以使用它所提供的IP地址。至此DHCP客户端可以使用DHCP服务器所提供的IP地址与网卡绑定。这里要注意,到这里为止,IP地址才真正为Android系统使用

这差不多是一个基本的过程了,还有一些服务器租约的内容,各位可以想一下,若是一台客户端一直占着某个IP,但是却没有使用,岂不是很大的浪费,所以就需要对服务器提供的IP设定时间限制,即所谓的租约,这里面dhcp客户端与dhcp服务器还有更细节的协商流程,各位有兴趣可以去了解下。

以上就是基本原理了,接下来就探讨下Android中的实现。

Android中的实现

结合以上的内容,在Android中寻找各个实体,在Android中,dhcp客户端是dhcpcd后台进程,它负责实际与dhcpcd服务器来进行交互。其源码位置如下:

/externel/dhcpcd/

但是实际上,Android一般不会直接通过dhcpcd去获取IP地址,而是使用了netcfg,它的源码路径如下:

/system/core/libnetutils/

这个程序会使用如下的格式去动态获取到IP地址:

netcfg  网口 dhcp

对于wifi来说,dhcp服务器即路由器,这时候,Android是和路由器进行交互的,而对于移动网络来说,dhcp服务器存在于modem基带(cp)中。

modem基带除了会虚拟网口,并在内部运行dhcp服务器供Android使用dhcp动态获取IP之外,同样会用AT指令的形式,向Android 上报其IP地址。

这篇文章我只是非常感性地叙述了这一流程,细节实际上很多,若是有兴趣的朋友,欢迎一起讨论!