iperf3 支持 android

iperf3是一个支持TCP, UDP, and SCTP 测带宽的工具。

最近在android上需要测带宽,编译了了一下它。

https://github.com/esnet/iperf

编译

sh 复制代码
# auto-detect connected device ABI
./build.sh

# build a specific ABI
./build.sh arm64-v8a

# build arm64-v8a + armeabi-v7a + x86_64 + x86
./build.sh all

# skip adb push
./build.sh --no-push

ubuntu安装使用

sh 复制代码
sudo apt install iperf3

使用

sh 复制代码
adb shell /data/local/tmp/iperf3 -s
adb shell /data/local/tmp/iperf3 -c <server-ip>

编译脚本

sh 复制代码
#!/usr/bin/env bash
# ------------------------------------------------------------------
# build.sh - Cross-compile iperf3 for Android and push to device.
#
# Usage:
#   ./build.sh                  # auto-detect connected device ABI
#   ./build.sh arm64-v8a        # build a specific ABI
#   ./build.sh all              # build arm64-v8a + armeabi-v7a + x86_64 + x86
#   ./build.sh --no-push        # skip adb push
#
# Env overrides:
#   ANDROID_NDK_HOME=/path/to/ndk   force a specific NDK
#   API=24                          minSdk (default 21)
# ------------------------------------------------------------------
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

API="${API:-21}"
PUSH_DEST="/data/local/tmp"
JOBS="$(nproc 2>/dev/null || echo 4)"

# ---------- Detect NDK ----------
detect_ndk() {
    local d
    for v in "${ANDROID_NDK_HOME:-}" "${NDK_HOME:-}" "${ANDROID_NDK:-}"; do
        [[ -n "$v" && -d "$v/toolchains/llvm/prebuilt/linux-x86_64" ]] && { echo "$v"; return; }
    done
    local candidates=()
    for d in "$HOME/Android/Sdk/ndk"/*  \
             "$HOME/Android/Sdk/ndk-bundle" \
             /opt/android-ndk-* \
             /usr/local/android-ndk-* \
             /opt/ndk/* ; do
        [[ -d "$d/toolchains/llvm/prebuilt/linux-x86_64/bin" ]] && candidates+=("$d")
    done
    if [[ ${#candidates[@]} -eq 0 ]]; then
        echo "ERROR: Android NDK not found. Set ANDROID_NDK_HOME." >&2
        exit 1
    fi
    # highest version wins
    printf '%s\n' "${candidates[@]}" | sort -V | tail -n1
}

NDK="$(detect_ndk)"
TOOLCHAIN="$NDK/toolchains/llvm/prebuilt/linux-x86_64"
echo ">>> NDK:       $NDK"
echo ">>> API level: $API"

# ---------- ABI helpers ----------
abi_to_triple() {
    case "$1" in
        arm64-v8a)   echo "aarch64-linux-android" ;;
        armeabi-v7a) echo "armv7a-linux-androideabi" ;;
        x86_64)      echo "x86_64-linux-android" ;;
        x86)         echo "i686-linux-android" ;;
        *) echo "ERROR: unsupported ABI: $1" >&2; exit 1 ;;
    esac
}

# The --host value passed to configure (uses 'arm' rather than 'armv7a')
abi_to_host() {
    case "$1" in
        arm64-v8a)   echo "aarch64-linux-android" ;;
        armeabi-v7a) echo "arm-linux-androideabi" ;;
        x86_64)      echo "x86_64-linux-android" ;;
        x86)         echo "i686-linux-android" ;;
    esac
}

# ---------- Detect connected device ABI ----------
detect_device_abi() {
    command -v adb >/dev/null 2>&1 || { echo ""; return; }
    local n
    n=$(adb devices 2>/dev/null | awk 'NR>1 && $2=="device"' | wc -l)
    [[ "$n" -eq 0 ]] && { echo ""; return; }
    adb shell getprop ro.product.cpu.abi 2>/dev/null | tr -d '\r\n'
}

# ---------- Parse args ----------
ABIS=()
DO_PUSH=1
for arg in "$@"; do
    case "$arg" in
        all)            ABIS+=(arm64-v8a armeabi-v7a x86_64 x86) ;;
        --no-push)      DO_PUSH=0 ;;
        -h|--help)      sed -n '2,15p' "$0"; exit 0 ;;
        arm64-v8a|armeabi-v7a|x86_64|x86) ABIS+=("$arg") ;;
        *) echo "Unknown argument: $arg" >&2; exit 1 ;;
    esac
done

if [[ ${#ABIS[@]} -eq 0 ]]; then
    dev_abi="$(detect_device_abi)"
    if [[ -n "$dev_abi" ]]; then
        echo ">>> Detected device ABI: $dev_abi"
        ABIS=("$dev_abi")
    else
        echo ">>> No device connected; defaulting to arm64-v8a"
        ABIS=(arm64-v8a)
    fi
fi

# ---------- Ensure configure exists ----------
if [[ ! -x ./configure ]]; then
    echo ">>> configure not found, running bootstrap.sh"
    ./bootstrap.sh
fi

# ---------- Build one ABI (out-of-tree) ----------
build_one() {
    local ABI="$1"
    local TRIPLE HOST CC_BIN BUILD_DIR OUT_DIR
    TRIPLE="$(abi_to_triple "$ABI")"
    HOST="$(abi_to_host "$ABI")"
    CC_BIN="$TOOLCHAIN/bin/${TRIPLE}${API}-clang"
    BUILD_DIR="build/$ABI"
    OUT_DIR="out/$ABI"

    echo
    echo "=================================================="
    echo ">>> Building iperf3 for $ABI"
    echo ">>>   triple: $TRIPLE   host: $HOST"
    echo ">>>   CC:     $CC_BIN"
    echo "=================================================="

    [[ -x "$CC_BIN" ]] || { echo "ERROR: compiler missing: $CC_BIN" >&2; exit 1; }

    rm -rf "$BUILD_DIR"
    mkdir -p "$BUILD_DIR" "$OUT_DIR"

    (
        cd "$BUILD_DIR"
        CC="$CC_BIN" \
        AR="$TOOLCHAIN/bin/llvm-ar" \
        RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
        STRIP="$TOOLCHAIN/bin/llvm-strip" \
        ../../configure \
            --host="$HOST" \
            --without-openssl \
            --disable-shared --enable-static \
            CFLAGS="-static -fPIE -O2" \
            LDFLAGS="-static -pie"
        make -j"$JOBS"
    )

    "$TOOLCHAIN/bin/llvm-strip" "$BUILD_DIR/src/iperf3"
    cp "$BUILD_DIR/src/iperf3" "$OUT_DIR/iperf3"
    echo ">>> Output: $OUT_DIR/iperf3"
    file "$OUT_DIR/iperf3" 2>/dev/null || true
}

for a in "${ABIS[@]}"; do
    build_one "$a"
done

# ---------- Push to device ----------
if [[ "$DO_PUSH" -eq 1 ]]; then
    if ! command -v adb >/dev/null 2>&1; then
        echo ">>> adb not in PATH; skip push."
        exit 0
    fi
    dev_abi="$(detect_device_abi)"
    if [[ -z "$dev_abi" ]]; then
        echo ">>> No device connected; skip push."
        exit 0
    fi

    push_bin=""
    for a in "${ABIS[@]}"; do
        [[ "$a" == "$dev_abi" ]] && push_bin="out/$a/iperf3"
    done
    # only one ABI built and it doesn't match device -> still push (user asked for it)
    if [[ -z "$push_bin" && ${#ABIS[@]} -eq 1 ]]; then
        push_bin="out/${ABIS[0]}/iperf3"
        echo ">>> Warning: built ABI (${ABIS[0]}) != device ABI ($dev_abi); pushing anyway."
    fi

    if [[ -z "$push_bin" || ! -f "$push_bin" ]]; then
        echo ">>> No matching build for device ABI $dev_abi; skip push."
        exit 0
    fi

    echo
    echo ">>> Pushing $push_bin -> $PUSH_DEST/iperf3"
    adb push "$push_bin" "$PUSH_DEST/iperf3"
    adb shell chmod 755 "$PUSH_DEST/iperf3"
    echo
    echo ">>> Version check on device:"
    adb shell "$PUSH_DEST/iperf3" -v || true
    echo
    echo ">>> Run on device with e.g.:"
    echo "    adb shell $PUSH_DEST/iperf3 -s"
    echo "    adb shell $PUSH_DEST/iperf3 -c <server-ip>"
fi

echo ">>> Done."
相关推荐
安卓修改大师6 小时前
安卓修改大师 vs MT管理器:反编译工具终极对决与全景解析
android·人工智能·机器翻译
程序员小八7777 小时前
从 0 学习 MySQL 索引——7 大核心精讲
android·学习·mysql
蓝速科技8 小时前
蓝速科技鸿蒙广告机替代安卓实测:信创系统下的性能与边界评估
android·科技·harmonyos
雅客李8 小时前
2026云手机高负载压力测评 安卓云手机多开实测数据
android·智能手机·php
千里马学框架10 小时前
google官方Perfetto 中使用 AI相关skill
android·人工智能·ai·framework·perfetto·性能·skill
zhangphil11 小时前
Android RecyclerView图像类ViewHolder离屏缓存数量直接增加Java/View对象内存,间接增加Graphics/GL内存
android
众少成多积小致巨12 小时前
Android C++ 编码规范指南
android·c++·google
DavidSu13 小时前
Kotlin协程原理解析
android
lxysbly13 小时前
Android PS3模拟器下载推荐2026|安卓PS3模拟器哪个好?手机玩PS3游戏指南
android·游戏·智能手机
qq_2468397514 小时前
记一次 Flutter 预热帧引起的初始化问题
android·flutter