当前位置: 首页 > news >正文

安卓学习24 -- 网络

1 整体架构

(出处见水印)

 这两张是能找到的比较清楚的图。目前可以看出,底层的网络业务,还是传统的linux内核提供。(注:这两个图我个人觉得不是非常对。。。

在安卓上增加的两个比较重要的部分分别是ConnectivityService和netd。这两个都是在system分区。通过socket和底层通信。

system分区和vendor分区区别如下:

分区功能
system(AOSP)提供标准的网络服务,如 ConnectivityService。同时,传统的linux网络服务比如DNS,iptables,routers等也在system分区。
vendor实现 HAL,比如 Wifi HAL、RIL(Radio Interface Layer),5G HAL
init.rc控制 netd 启动、网络接口初始化

ConnectivityService提供上层封装给app,通过binder连接netd,netd封装了底层网络功能和驱动HAL。

2 ConnectivityManager/ConnectivityService

2.1 ConnectivityManager

使用还是比较简单,在app层主要就是ConnectivityManager,不过这里只能获取一些网络信息。
API文档:https://developer.android.com/reference/android/net/ConnectivityManage

下面是一些示例代码。

package com.example.connectivitytest;import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.content.Context;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.net.NetworkCapabilities;public class MainActivity extends AppCompatActivity {private TextView networkStatus;private TextView networkStatus1;private TextView networkStatus2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);networkStatus = findViewById(R.id.network_status);ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);if (cm != null) {NetworkInfo activeNetwork = cm.getActiveNetworkInfo();boolean isConnected = activeNetwork != null && activeNetwork.isConnected();if (isConnected) {String type = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI ? "Wi-Fi" : "Mobile Data";networkStatus.setText("Connected via: " + type);} else {networkStatus.setText("Not Connected");}} else {networkStatus.setText("ConnectivityManager unavailable");}NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());boolean hasInternet = capabilities != null &&capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);networkStatus1 = findViewById(R.id.network_status1);if(hasInternet) {networkStatus1.setText("Has Internet");}networkStatus2 = findViewById(R.id.network_status2);Network[] allNetworks = cm.getAllNetworks();String info = "Network Info :";for (Network network : allNetworks) {NetworkCapabilities caps = cm.getNetworkCapabilities(network);//Log.d("Network Info", caps.toString());info += caps.toString();}networkStatus2.setText(info);}
}

在上层还有一些,比如WifiManager、TelephonyManager。

2.2 ConnectivityService

提供了上层很多自动控制功能。比如自动网络切换,自动VPN,节省流程等等。很多针对网络的控制逻辑是在这个部分处理。

这下面内容还是挺多。

常用命令

# 查看当前网络状态
adb shell dumpsys connectivity# 监控网络事件
adb shell dumpsys connectivity event# 检查NetworkPolicy
adb shell dumpsys netpolicy

在这一层,可以动态监测丢包率,从而控制应用使用不同的带宽。

3 netd

3.1 整体说明

在安卓的网络结构中,netd处在更核心的位置。netd的位置大致如下: 

 

netd 提供的内容如下:
防火墙配置(iptables):netd 负责配置和管理防火墙规则。它通过 iptables 命令来处理传入和传出的网络流量。

它还管理 NAT(网络地址转换)和数据包过滤功能。

DNS 配置:netd 负责管理 DNS 配置,包括配置 DNS 服务器和处理 DNS 查询。

IP 地址管理:它管理设备的网络接口,分配和管理 IP 地址等。例如,当设备连接到 Wi-Fi 或蜂窝网络时,netd 会分配 IP 地址。

网络路由管理:netd 配置并管理网络路由规则,确定数据包的转发路径。

VPN 管理:它处理与 VPN 相关的操作,包括路由网络流量、配置 VPN 接口等。

网络统计和监控:netd 提供了对网络连接、数据流量、接口状态等的统计和监控能力。

代码是在system/netd/,下载了一下代码,也不是太多东西,如下:

 主要还是server里面的东西

 瞟了一眼大概就是除了binder的内容,就是firewall,interface,iptables,netlink,router这就几个老同志。

3.2 iptables

IptablesProcess* IptablesRestoreController::forkAndExec(const IptablesProcessType type) {const char* const cmd = (type == IPTABLES_PROCESS) ?IPTABLES_RESTORE_PATH : IP6TABLES_RESTORE_PATH;// Create the pipes we'll use for communication with the child// process. One each for the child's in, out and err files.int stdin_pipe[2];int stdout_pipe[2];int stderr_pipe[2];// Assumes stdin, stdout, stderr are already in use.if (pipe2(stdin_pipe,  O_CLOEXEC) == -1 ||pipe2(stdout_pipe, O_NONBLOCK | O_CLOEXEC) == -1 ||pipe2(stderr_pipe, O_NONBLOCK | O_CLOEXEC) == -1) {ALOGE("pipe2() failed: %s", strerror(errno));return nullptr;}const auto& sys = sSyscalls.get();StatusOr<pid_t> child_pid = sys.fork();if (!isOk(child_pid)) {ALOGE("fork() failed: %s", strerror(child_pid.status().code()));return nullptr;}if (child_pid.value() == 0) {// The child process. Reads from stdin, writes to stderr and stdout.// stdin_pipe[0] : The read end of the stdin pipe.// stdout_pipe[1] : The write end of the stdout pipe.// stderr_pipe[1] : The write end of the stderr pipe.// Note: dup2 does not set O_CLOEXEC. std*_pipe[*] is closed by execl.if (dup2(stdin_pipe[0], 0) == -1 ||dup2(stdout_pipe[1], 1) == -1 ||dup2(stderr_pipe[1], 2) == -1) {ALOGE("dup2() failed: %s", strerror(errno));abort();}if (execl(cmd,cmd,"--noflush",  // Don't flush the whole table."-w",         // Wait instead of failing if the lock is held."-v",         // Verbose mode, to make sure our ping is echoed// back to us.nullptr) == -1) {ALOGE("execl(%s, ...) failed: %s", cmd, strerror(errno));abort();}// This statement is unreachable. We abort() upon error, and execl// if everything goes well.return nullptr;}// The parent process.if (close(stdin_pipe[0]) == -1 ||close(stdout_pipe[1]) == -1 ||close(stderr_pipe[1]) == -1) {ALOGW("close() failed: %s", strerror(errno));}// stdin_pipe[1] : The write end of the stdin pipe.// stdout_pipe[0] : The read end of the stdout pipe.// stderr_pipe[0] : The read end of the stderr pipe.return new IptablesProcess(type,child_pid.value(), stdin_pipe[1], stdout_pipe[0], stderr_pipe[0]);
}

可以看出就是调用的iptables-restore命令。

3.3 interface接口

// Run @fn on each interface as well as 'default' in the path @dirname.
void forEachInterface(const std::string& dirname,const std::function<void(const std::string& path, const std::string& iface)>& fn) {// Run on default, which controls the behavior of any interfaces that are created in the future.fn(dirname, "default");DIR* dir = opendir(dirname.c_str());if (!dir) {ALOGE("Can't list %s: %s", dirname.c_str(), strerror(errno));return;}while (true) {const dirent *ent = readdir(dir);if (!ent) {break;}if ((ent->d_type != DT_DIR) || !isInterfaceName(ent->d_name)) {continue;}fn(dirname, ent->d_name);}closedir(dir);
}

可以看出,还是直接用的linux的网络接口,从/proc/sys/net/ipv4/conf去获取数据

3.4 NDC

这个就是命令行下的netd操作工具。

网络接口

ndc interface list
ndc interface show eth0
ndc interface setcfg eth0 192.168.1.2 24 up
ndc interface getcfg eth0
ndc interface clearaddrs eth0

DNS

ndc resolver setnetdns <netId> <domain> <dns1> [dns2] ...
ndc resolver getnetdns <netId>
ndc resolver flushdefaultif

防火墙

ndc firewall enable
ndc firewall disable
ndc firewall set_interface_rule wlan0 allow
ndc firewall set_uid_rule standby 1000 allow

网络策略

ndc bandwidth enable
ndc bandwidth disable
ndc bandwidth addnaughtyapps 10064
ndc bandwidth removenaughtyapps 10064

Tethering(共享网络)

ndc tether interface add rndis0
ndc tether interface remove rndis0
ndc tether start
ndc tether stop

其它。。。

4 其它的命令

工具用途
ip / ifconfig传统网络命令,底层操作网络接口
iptables / ip6tables控制防火墙规则
netstat / ss查看网络连接状态
ping / traceroute测试网络连通性
setprop / getprop设置和读取系统属性(部分 netd 配置通过属性控制)
logcat查看 netd 输出日志
strace / lsof调试辅助工具,查看 netd 打开的文件、socket 等

好了,就是简单看看,先这样吧。。。 


http://www.mrgr.cn/news/99151.html

相关文章:

  • AnimateCC基础教学:制作一个打地鼠简化版
  • 06 GE Modifier
  • 使用注解方式整合ssm时,启动tomcat扫描不到resource下面的xxxmapper.xml问题,解决方法
  • dawgctf 2025 writeup
  • 从零起步的Kaggle竞赛 - BirdCLEF2025
  • Python多任务编程:进程全面详解与实战指南
  • 实现AWS Lambda函数安全地请求企业内部API返回数据
  • 【C++详解】C++入门(一)命名空间、缺省参数、函数重载
  • Linux安装mysql_exporter
  • 第 28 场 蓝桥月赛
  • 线性DP:最长上升子序列(子序列可不连续,子数组必须连续)
  • C++ 模块化编程(Modules)在大规模系统中的实践难点
  • acwing--动态规划【线性dp】4/20、4/21
  • 大数据应用开发——大数据平台集群部署(四)
  • 机器学习专栏(4):从数据饥荒到模型失控,破解AI训练的七大生死劫
  • 分布类相关的可视化图像
  • 基于maven-jar-plugin打造一款自动识别主类的maven打包插件
  • 单元测试的一般步骤
  • 20. git diff
  • 超简单的git学习教程