Android O/P/Q 版本移植iperf网络性能测试工具

本文涉及的产品
性能测试 PTS,5000VUM额度
简介: Android O/P/Q 版本移植iperf网络性能测试工具

iperf是什么


Iperf 是一个网络性能测试工具,是跨平台的,支持Window,linux,android平台的运行和测试,可以为任何网络生成标准化的性能测量。


Iperf 可以测试最大 TCP 和 UDP 带宽性能,具有多种参数和UDP特性,可以根据需要调整,可以报告带宽、延迟抖动和数据包丢失。


源代下载地址:https://storage.googleapis.com/google-code-archive-source/v2/code.google.com/iperf/source-archive.zip


下载可能会很慢,不行去 https://iperf.fr/iperf-download.php 下载 linux 版本源码


移植步骤


1、解压 iperf 源码,放置到android源码目录下,这里以 system/ 目录为例,你也可以放到 package/app 或者其它目录


2、删除源码目录下的 Makefile.am 和 Makefile.in 文件 以及 src 目录下 Makefile.am 、Makefile.in、Makefile.old


3、新增 Android.mk, 加入如下配置

LOCAL_PATH := $(call my-dir)
# Device executable.
# =========================================================
include $(CLEAR_VARS)
LOCAL_MODULE := iperf
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/src
LOCAL_SRC_FILES := $(call all-c-files-under, src)
LOCAL_CFLAGS := -Wno-error -DIPERF_HOST=0
LOCAL_MODULE_TAGS := debug
LOCAL_FORCE_STATIC_EXECUTABLE := true
# LOCAL_LDLIBS += -llog
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
LOCAL_STATIC_LIBRARIES := libutils liblog
include $(BUILD_EXECUTABLE)

遇到的坑


1、config.h 文件找不到,源码中的文件是 config.h.in, 去掉后缀 .in 即可

system/iperf/src/iperf_util.c:29:10: fatal error: 'config.h' file not found
#include "config.h"
         ^~~~~~~~~~
1 error generated.
[ 42% 11/26] target  C: iperf <= system/iperf/src/iperf_tcp.c

2、结构体 in6_flowlabel_req 重复定义,解决办法 flowlabel.h 中结构体外增加条件编译控制


In file included from system/iperf/src/iperf_tcp.c:29:
system/iperf/src/flowlabel.h:22:8: error: redefinition of 'in6_flowlabel_req'
struct in6_flowlabel_req
       ^
bionic/libc/kernel/uapi/linux/in6.h:55:8: note: previous definition is here
struct in6_flowlabel_req {
       ^
1 error generated.
*/
#if IPERF_HOST
struct in6_flowlabel_req
{
    struct in6_addr flr_dst;
    __u32   flr_label;
    __u8    flr_action;
    __u8    flr_share;
    __u16   flr_flags;
    __u16   flr_expires;
    __u16   flr_linger;
    __u32   __flr_pad;
    /* Options in format of IPV6_PKTOPTIONS */
};
#endif


3、main 函数冲突错误,删除 src/t_uuid.c、src/t_timer.c 和 src/t_units.c 三个文件

prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: error: out/target/product/k37tv1_64_bsp/obj/EXECUTABLES/iperf_intermediates/src/t_timer.o: multiple definition of 'main'
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: out/target/product/k37tv1_64_bsp/obj/EXECUTABLES/iperf_intermediates/src/main.o: previous definition here
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: error: out/target/product/k37tv1_64_bsp/obj/EXECUTABLES/iperf_intermediates/src/t_units.o: multiple definition of 'main'
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: out/target/product/k37tv1_64_bsp/obj/EXECUTABLES/iperf_intermediates/src/main.o: previous definition here
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: error: out/target/product/k37tv1_64_bsp/obj/EXECUTABLES/iperf_intermediates/src/t_uuid.o: multiple definition of 'main'
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/ld.gold: out/target/product/k37tv1_64_bsp/obj/EXECUTABLES/iperf_intermediates/src/main.o: previous definition here
clang.real: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
16:16:14 ninja failed with: exit status 1


4、然后再编译,你就阔仪得到 iperf 文件了,输出路径位于 system/xbin/ 下

[ 83% 5/6] target Strip (mini debug info): iperf (out/target/product/k37tv1_64_bsp/obj/EXECUTABLES/iperf_intermediates/iperf)
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-nm: out/target/product/k37tv1_64_bsp/symbols/system/xbin/iperf: no symbols
[100% 6/6] Install: out/target/product/k37tv1_64_bsp/system/xbin/iperf
#### build completed successfully (44 seconds) ####


5、把 system/xbin/iperf文件 push 到设备中,adb shell 执行命令


先给 iperf 赋权, chmod 777 system/xbin/iperf,然后开启服务端,再执行


iperf -c 192.168.40.37 -p 5201 -t 10


Connecting to host 192.168.40.37, port 5201

iperf3: error - unable to create a new stream: No such file or directory


提示错误,这是因为 iperf 执行时需要指定缓存目录,源码中用的是 char template[] = “/tmp/iperf3.XXXXXX”;


O 以上已经没有 tmp 目录了,将其修改为 char template[] = “/data/local/tmp/iperf3.XXXXXX”;


重新编译push


这样就能正常使用 iperf 工具了

Connecting to host 192.168.40.37, port 5201
[  4] local 192.168.3.4 port 34986 connected to 192.168.40.37 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.07   sec  2.12 MBytes  16.6 Mbits/sec   73   37.2 KBytes
[  4]   1.07-2.11   sec  1.00 MBytes  8.11 Mbits/sec    0   44.1 KBytes
[  4]   2.11-3.17   sec  1.00 MBytes  7.87 Mbits/sec    1   40.0 KBytes
[  4]   3.17-4.10   sec  1.25 MBytes  11.3 Mbits/sec    0   46.9 KBytes
[  4]   4.10-5.00   sec  1.88 MBytes  17.5 Mbits/sec    0   52.4 KBytes
[  4]   5.00-6.00   sec  1.62 MBytes  13.6 Mbits/sec    5   45.5 KBytes
[  4]   6.00-7.10   sec  1.75 MBytes  13.4 Mbits/sec    2   41.4 KBytes
[  4]   7.10-8.20   sec  1.12 MBytes  8.58 Mbits/sec    0   46.9 KBytes
[  4]   8.20-9.20   sec   512 KBytes  4.19 Mbits/sec    0   48.3 KBytes
[  4]   9.20-10.10  sec   640 KBytes  5.82 Mbits/sec    3   35.9 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.10  sec  12.9 MBytes  10.7 Mbits/sec   84             sender
[  4]   0.00-10.10  sec  12.7 MBytes  10.5 Mbits/sec                  receiver
iperf Done.


app 中调用 iperf


每次都需要在 adb shell 下调用测速,其实在 java 代码中也能,通过 Runtime.getRuntime().exec() 执行 iperf 指令

successMsg: Connecting to host 192.168.40.37, port 5201


errorMsg: iperf3: error - unable to create a new stream: Permission denied


在 app 执行时又返回 unable to create a new stream 错误,看来 char template[] 路径还得修改,试了好几个目录后,


最终指定到 sdcard/下解决了问题, char template[] = “/sdcard/iperf3.XXXXXX”;


String cmds = "iperf -c  192.168.40.37 -p 5201 -t 10";
 CommandResult result = execCmd(cmds, false, true);
 String fullResult = result.toString();
public static CommandResult execCmd(final String[] commands,
                                        final boolean isRooted,
                                        final boolean isNeedResultMsg) {
        int result = -1;
        if (commands == null || commands.length == 0) {
            return new CommandResult(result, "", "");
        }
        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;
        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec(isRooted ? "su" : "sh");
            os = new DataOutputStream(process.getOutputStream());
            for (String command : commands) {
                if (command == null) {
                    continue;
                }
                os.write(command.getBytes());
                os.writeBytes(LINE_SEP);
                os.flush();
            }
            os.writeBytes("exit" + LINE_SEP);
            os.flush();
            result = process.waitFor();
            if (isNeedResultMsg) {
                successMsg = new StringBuilder();
                errorMsg = new StringBuilder();
                successResult = new BufferedReader(
                        new InputStreamReader(process.getInputStream(), "UTF-8")
                );
                errorResult = new BufferedReader(
                        new InputStreamReader(process.getErrorStream(), "UTF-8")
                );
                String line;
                if ((line = successResult.readLine()) != null) {
                    successMsg.append(line);
                    while ((line = successResult.readLine()) != null) {
                        successMsg.append(LINE_SEP).append(line);
                    }
                }
                if ((line = errorResult.readLine()) != null) {
                    errorMsg.append(line);
                    while ((line = errorResult.readLine()) != null) {
                        errorMsg.append(LINE_SEP).append(line);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (successResult != null) {
                    successResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (process != null) {
                process.destroy();
            }
        }
        return new CommandResult(
                result,
                successMsg == null ? "" : successMsg.toString(),
                errorMsg == null ? "" : errorMsg.toString()
        );
    }

下载我编译好的 iperf


MTK-Android-CZ-Code/iperf/


参考文章


https://www.sdnlab.com/2961.html


https://www.cnblogs.com/0xcafebabe/p/10685938.html


https://blog.csdn.net/Sunxiaolin2016/article/details/100112339

相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
目录
相关文章
|
1月前
|
机器学习/深度学习 PyTorch 算法框架/工具
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
这篇文章介绍了如何使用PyTorch框架,结合CIFAR-10数据集,通过定义神经网络、损失函数和优化器,进行模型的训练和测试。
88 2
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
|
3月前
|
SQL 安全 测试技术
网络安全的屏障与钥匙:漏洞防护与加密技术解析软件测试的艺术:探索性测试的力量
【8月更文挑战第27天】在数字时代的海洋中,网络安全是保护我们数据资产的灯塔和堤坝。本文将深入浅出地探讨网络安全领域的关键要素——安全漏洞、加密技术以及不可或缺的安全意识。通过实际案例分析,我们将了解如何识别和修补潜在的安全漏洞,掌握现代加密技术的工作原理,并培养起一道坚固的安全防线。文章旨在为读者提供实用的知识和技能,以便在日益复杂的网络环境中保持警惕,确保个人及组织信息的安全。
|
3月前
|
机器学习/深度学习
神经网络与深度学习---验证集(测试集)准确率高于训练集准确率的原因
本文分析了神经网络中验证集(测试集)准确率高于训练集准确率的四个可能原因,包括数据集大小和分布不均、模型正则化过度、批处理后准确率计算时机不同,以及训练集预处理过度导致分布变化。
|
7天前
|
网络虚拟化
生成树协议(STP)及其演进版本RSTP和MSTP,旨在解决网络中的环路问题,提高网络的可靠性和稳定性
生成树协议(STP)及其演进版本RSTP和MSTP,旨在解决网络中的环路问题,提高网络的可靠性和稳定性。本文介绍了这三种协议的原理、特点及区别,并提供了思科和华为设备的命令示例,帮助读者更好地理解和应用这些协议。
21 4
|
11天前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
|
17天前
|
编解码 安全 Linux
网络空间安全之一个WH的超前沿全栈技术深入学习之路(10-2):保姆级别教会你如何搭建白帽黑客渗透测试系统环境Kali——Liinux-Debian:就怕你学成黑客啦!)作者——LJS
保姆级别教会你如何搭建白帽黑客渗透测试系统环境Kali以及常见的报错及对应解决方案、常用Kali功能简便化以及详解如何具体实现
|
22天前
|
网络协议 Shell 网络安全
解决两个 Android 模拟器之间无法网络通信的问题
让同一个 PC 上运行的两个 Android 模拟器之间能相互通信,出(qiong)差(ren)的智慧。
22 3
|
1月前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
46 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
17天前
|
人工智能 安全 Linux
网络空间安全之一个WH的超前沿全栈技术深入学习之路(4-2):渗透测试行业术语扫盲完结:就怕你学成黑客啦!)作者——LJS
网络空间安全之一个WH的超前沿全栈技术深入学习之路(4-2):渗透测试行业术语扫盲完结:就怕你学成黑客啦!)作者——LJS
|
17天前
|
安全 大数据 Linux
网络空间安全之一个WH的超前沿全栈技术深入学习之路(3-2):渗透测试行业术语扫盲)作者——LJS
网络空间安全之一个WH的超前沿全栈技术深入学习之路(3-2):渗透测试行业术语扫盲)作者——LJS