Bootstrap

adb端口转发

adb server 运行在 PC 端,监听 localhost:5037 端口的实现原理涉及 Socket 编程、进程管理、消息处理机制 以及 客户端-服务器架构(Client-Server Architecture)。其核心机制如下:


1. ADB 的三大核心组件

adb 采用 C/S 架构(Client-Server Architecture),主要包含三部分:

  1. adb client(客户端)

    • 运行在 PC 端,用户执行 adb 命令(如 adb devices, adb forward)。
    • 负责与 adb server 通信,发送命令并处理返回的结果。
  2. adb server(服务器)

    • 运行在 PC 端,监听 localhost:5037 端口,管理多个 adb 连接。
    • 负责与多个 adb client 交互,并管理 adbd 进程(运行在 Android 设备上)。
  3. adbd daemon(守护进程)

    • 运行在 Android 设备端,负责处理 adb server 发送的命令,并执行设备操作(如端口转发、文件传输、shell 命令)。
    • 通过 USB 或 TCP/IP 与 adb server 进行通信。

2. adb server 监听 localhost:5037 的实现原理

2.1 adb server 进程启动

当执行 adb 命令(如 adb devices)时:

  1. adb client 首先检查 adb server 是否已运行:

    LocalSocket socket;
    socket.connect("localhost", 5037);
    
    • 尝试连接 localhost:5037 端口,判断 adb server 是否在运行。
  2. 如果 adb server 未运行

    • adb client 启动 adb server 进程:
      adb_forkserver();
      
    • adb server 在后台运行,监听 localhost:5037 端口。

2.2 adb server 监听 localhost:5037

  1. adb server 采用 TCP Server 模型:

    • 使用 socket(AF_INET, SOCK_STREAM, 0) 创建监听 socket。
    • 绑定 localhost:5037,监听新的 adb 连接:
      int server_fd = socket(AF_INET, SOCK_STREAM, 0);
      sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(5037);
      addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // 监听 127.0.0.1
      bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));
      listen(server_fd, 5);
      
    • INADDR_LOOPBACK 限制了 adb server 只能在本机访问,确保安全性。
  2. 等待 adb client 连接

    • adb server 通过 accept() 等待 adb client 连接:
      int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len);
      
    • adb client 连接后,adb server 解析客户端发送的命令(如 adb devicesadb forward)。

2.3 adb serveradbd 进程通信

  1. 建立 USB 连接

    • adb server 通过 USB 端口(usb_device_open())连接 Android 设备:
      usb_handle* usb = usb_device_open();
      
    • adb server 发送 host:transport-usb 命令,绑定到 Android 设备。
  2. 建立 TCP 连接

    • 如果 adb 采用 Wi-Fi 连接(adb connect <device_ip>:5555),则:
      int device_socket = socket(AF_INET, SOCK_STREAM, 0);
      sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(5555);
      addr.sin_addr.s_addr = inet_addr(device_ip);
      connect(device_socket, (struct sockaddr*)&addr, sizeof(addr));
      
    • adb server 连接 adbd,数据流通过 TCP 传输。
  3. 数据交互

    • adb server 解析 adb client 的请求,如 adb shelladb pushadb forward,并通过 USB/TCP 发送给 adbd
    • adbd 执行命令后返回结果,adb server 再返回给 adb client

3. adb server 监听 5037 的意义

  1. 管理多个设备

    • adb server 统一管理所有连接的 Android 设备,包括 USB 和 TCP/IP 设备。
  2. 提高效率

    • 避免每次 adb 命令都重新建立与 adbd 的连接,减少资源消耗。
  3. 允许并发命令

    • 多个 adb client 可以同时向 adb server 发送命令,例如:
      adb shell
      adb push file.txt /sdcard/
      
    • adb server 处理多个请求,提高并发能力。

4 在中转机上运行 ADB

###############
# 在中转机上跑
###############
sudo killall adb
sudo nohup adb -a nodaemon server &
sudo adb devices
ADB_ID=ABCD1234  # adb devices 显示的设备ID
sudo adb -s ${ADB_ID} tcpip 5555
sleep 3
sudo adb -s ${ADB_ID} forward tcp:5555 tcp:5555
sudo adb -s ${ADB_ID} forward tcp:8000 tcp:8000

###############
# 在测评机上跑
###############
adb connect 100.10.20.3:5555

这段脚本的作用是 在一台“中转机”上运行 ADB 代理,然后 在另一台“测评机”上通过 ADB 远程连接 Android 设备。整个流程可以分为 “中转机设置”“测评机连接” 两个部分。

4.1 在中转机上运行 ADB 代理

sudo killall adb
  • 终止所有正在运行的 adb 进程,确保 ADB 重新启动时不会有冲突。
sudo nohup adb -a nodaemon server &
  • 启动 adb server,并使其在后台运行:
    • -a:监听所有网络接口(默认 adb server 只监听 localhost)。
    • nodaemon:不以守护进程方式运行,适用于 nohup 后台执行。
    • nohup:防止进程因 SSH 断开而退出。

4.2 确保设备连接

sudo adb devices
  • 列出所有已连接的设备,格式:
    List of devices attached
    ABCD1234    device
    
  • 这里的 ABCD1234 是 Android 设备的唯一标识符(serial number)。
ADB_ID=ABCD1234  # adb devices 显示的设备ID
  • 将设备 ID 存入变量,方便后续使用。

4.3 切换 ADB 到 TCP/IP 模式

sudo adb -s ${ADB_ID} tcpip 5555
  • 让 Android 设备开启 TCP/IP ADB 监听
    • 设备上的 adbd 进程会开始监听 TCP 端口 5555,允许远程 ADB 连接。
    • 设备必须已启用 adb 调试模式,并连接到 USB,否则命令会失败。
sleep 3
  • 等待 3 秒,确保 adbd 进程成功切换到 tcpip 模式。

4.4 在中转机上做端口转发

sudo adb -s ${ADB_ID} forward tcp:5555 tcp:5555
  • 端口转发(Forwarding)
    • 中转机的 localhost:5555 代理 Android 设备的 localhost:5555
    • 这样,外部设备可以通过 中转机:5555 访问 Android 设备的 adb 端口。
sudo adb -s ${ADB_ID} forward tcp:8000 tcp:8000
  • 额外转发 端口 8000,可能用于 Android 设备上运行的某个 Web 服务或调试工具(如 WebSocketgRPC)。

adb connect 10.1.2.3:5555
  • 让测评机 通过网络连接到中转机(10.1.2.3)的 5555 端口
    • 10.1.2.3 是中转机的 IP 地址。
    • 因为中转机 已将 5555 端口转发到 Android 设备,所以测评机的 adb connect 最终连接的是 Android 设备

步骤命令作用
1. 杀死旧的 ADB 进程sudo killall adb避免冲突
2. 启动 ADB 服务器sudo nohup adb -a nodaemon server &监听 ADB 连接
3. 获取设备 IDadb devices识别 Android 设备
4. 启用 TCP/IP ADBadb -s ${ADB_ID} tcpip 5555让 Android 设备监听 5555 端口
5. 端口转发(ADB 代理)adb -s ${ADB_ID} forward tcp:5555 tcp:5555让中转机监听 5555 端口
6. 测评机连接adb connect 10.1.2.3:5555远程访问 Android 设备

4.7 防止 ADB 断连

如果 Android 设备 adbd 进程自动关闭,导致 adb connect 失效,可以:

while true; do adb connect 10.1.2.3:5555; sleep 5; done
  • 每 5 秒尝试重新连接

4.8 让 ADB 连接更稳定

在 Android 设备上执行:

setprop service.adb.tcp.port 5555
stop adbd
start adbd
  • 使 ADB 端口持久化,避免设备重启后 adb tcpip 5555 失效。

;