安卓学习24 -- 网络

news2025/4/21 11:28:45

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;

    @Override
    protected 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.coloradmin.cn/o/2339393.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

github新建一个远程仓库并添加了README.md,本地git仓库无法push

1.本地git仓库与远程仓库绑定 2.push时报错&#xff0c;本地的 main 分支落后于远程仓库的 main 分支&#xff08;即远程有更新&#xff0c;但你本地没有&#xff09;&#xff0c;需要拉取远程的仓库--->在merge合并&#xff08;解决冲突&#xff09;--->push 3.但是git …

Python:使用web框架Flask搭建网站

Date: 2025.04.19 20:30:43 author: lijianzhan Flask 是一个轻量级的 Python Web 开发框架&#xff0c;以简洁灵活著称&#xff0c;适合快速构建中小型 Web 应用或 API 服务。以下是 Flask 的核心概念、使用方法和实践指南 Flask 的核心特点&#xff1a; 轻量级 核心代码仅约…

Kotlin delay方法解析

本文记录了kotlin协程(Android)中delay方法的字节码实现&#xff0c;并解析了delay方法如何实现挂起操作。 一、delay方法介绍 1.1、delay方法使用举例 class TestDelay {suspend fun testDelay() {Log.d("TestDelay", "before delay")delay(1000)Log.d…

【Vulkan 入门系列】创建描述符集布局和图形管线(五)

描述符集布局定义了着色器如何访问资源&#xff08;如缓冲区和图像&#xff09;&#xff0c;是渲染管线配置的关键部分。图形管线定义了从顶点数据到最终像素输出的整个处理流程&#xff0c;包括可编程阶段&#xff08;如顶点和片段着色器&#xff09;和固定功能阶段&#xff0…

mysql中in的用法详解

MySQL 中 IN 操作符用法详解 IN 是 MySQL 中用于多值筛选的高效操作符&#xff0c;常用于 WHERE 子句&#xff0c;可替代多个 OR 条件&#xff0c;简化查询逻辑并提升可读性。以下从基础语法、应用场景、性能优化、常见问题及高级技巧进行全方位解析。 一、基础语法与优势 1.…

MySQL为什么默认使用RR隔离级别?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL为什么默认使用RR隔离级别?】面试题。希望对大家有帮助&#xff1b; MySQL为什么默认使用RR隔离级别? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MySQL 默认使用 RR&#xff08;Repeatable Read&#xff09;…

施磊老师基于muduo网络库的集群聊天服务器(二)

文章目录 Cmake简单介绍Cmake与MakefileCmake配置CmakeLists.txt 编写完整cmake例子文件夹杂乱问题多级目录Cmakevscode 极其推荐 的 cmake方式 Mysql环境与编程mysql简单使用User表Friend表AllGroup表GroupUser表OfflineMessage表 集群聊天项目工程目录创建网络模块代码Chatse…

线性DP:最长上升子序列(子序列可不连续,子数组必须连续)

目录 Q1&#xff1a;简单遍历 Q2&#xff1a;变式&#xff08;加大数据量&#xff09; Q1&#xff1a;简单遍历 Dp问题 状态表示 f(i,j) 集合所有以第i个数结尾的上升子序列集合-f(i,j)的值存的是什么序列长度最大值max- 状态计算 &#xff08;其实质是集合的划分&#xff09;…

C语言之文本加密程序设计

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 文本加密程序设计 摘要&#xff1a;本文设计了一种文本加密程序&#xff0c;旨在提高信息安…

云效部署实现Java项目自动化部署图解

前言 记录下使用云效部署Java项目&#xff0c;实现java项目一键化自动化部署。 云效流程说明&#xff1a; 1.云效拉取最新git代码后 2.进行maven编译打包后&#xff0c;上传到指定服务器目录 3.通过shell脚本&#xff0c;先kill java项目后&#xff0c;通过java -jar 启动项…

0801ajax_mock-网络ajax请求1-react-仿低代码平台项目

0 vite配置proxy代理 vite.config.ts代码如下图所示&#xff1a; import { defineConfig } from "vite"; import react from "vitejs/plugin-react";// https://vite.dev/config/ export default defineConfig({plugins: [react()],server: {proxy: {&qu…

基于Python智能体API的Word自动化排版系统:从零构建全流程模块化工作流与版本控制研究

基于Python智能体API的Word自动化排版系统:从零构建全流程模块化工作流与版本控制实践研究 1. 引言2. 研究背景与意义3. 自动排版工作流的设计原理3.1 文档内容提取与解析3.2 样式参数与格式化规则3.3 智能体API接口调用3.4 自动生成与批量处理3.5 与生成式AI的协同4. 系统架构…

Java【网络原理】(4)HTTP协议

目录 1.前言 2.正文 2.1自定义协议 2.2HTTP协议 2.2.1抓包工具 2.2.2请求响应格式 2.2.2.1URL 2.2.2.2urlencode 2.2.3认识方法 2.2.3.1GET与POST 2.2.3.2PUT与DELETE 2.2.4请求头关键属性 3.小结 1.前言 哈喽大家好啊&#xff0c;今天来继续给大家带来Java中网络…

每天学一个 Linux 命令(27):head

​​可访问网站查看,视觉品味拉满: http://www.616vip.cn/27/index.html head 是 Linux 中用于查看文件开头部分内容的命令,默认显示文件前 10 行,适合快速预览文件结构或日志头部信息。 命令格式 head [选项] [文件]常用选项 选项说明-n <行数>指定显示前 N 行(如…

【2025软考高级架构师】——计算机系统基础(7)

摘要 本文主要介绍了计算机系统的组成&#xff0c;包括硬件和软件两大部分。硬件由处理器、存储器、总线、接口和外部设备等组成&#xff0c;软件则涵盖系统软件和应用软件。文章还详细阐述了冯诺依曼计算机的组成结构&#xff0c;包括 CPU、主存储器、外存等&#xff0c;并解…

LeetCode 打家劫舍+删除并获得点数

题目描述 打家劫舍题目传送门1 删除并获得点数传送门2 思路 这两道题看似毫无关系&#xff0c;但竟然可以用桶数组联系起来&#xff01;&#xff01; 先说打家劫舍这道题 限制条件是不能走相邻的屋&#xff0c;再联想到跳台阶&#xff08;走一格或两格&#xff09;&#x…

图解MCP:Model Context Protocol

&#x1f9e0; 向所有学习者致敬&#xff01; “学习不是装满一桶水&#xff0c;而是点燃一把火。” —— 叶芝 我的博客主页&#xff1a; https://lizheng.blog.csdn.net &#x1f310; 欢迎点击加入AI人工智能社区&#xff01; &#x1f680; 让我们一起努力&#xff0c;共创…

【网络】数据链路层知识梳理

全是通俗易懂的讲解&#xff0c;如果你本节之前的知识都掌握清楚&#xff0c;那就速速来看我的笔记吧~ 自己写自己的八股&#xff01;让未来的自己看懂&#xff01; &#xff08;全文手敲&#xff0c;受益良多&#xff09; 数据链路层 我们来重新理解一下这个图&#xff1a;…

积木报表查询出现jdbc.SQLServerException: 对象名 ‘user_tab_comment 的解决方法

目录 前言1. 问题所示2. 解决方法前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn 1. 问题所示 使用帆软报表无错,后续使用积木报表查询出错: 没有显示报表: 具体错误信息如下:

数字孪生废气处理工艺流程

图扑数字孪生废气处理工艺流程系统。通过精准 3D 建模&#xff0c;对废气收集、预处理、净化、排放等全流程进行 1:1 数字化复刻&#xff0c;实时呈现设备运行参数、污染物浓度变化等关键数据。 借助图扑可视化界面&#xff0c;管理者可直观掌握废气处理各环节状态&#xff0c…