Jacky's blog
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)

Jack Yang

编程; 随笔
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)
  • tutorial
  • jetpack

  • components

  • androidx

  • 动态化
  • apm

  • module

  • harmony

  • tool

  • other

    • Flutter 高频面试问答
    • 生产环境Message分发处理设计
    • Android 事件分发机制
    • android沉浸式设置
    • 调研抖音对harmonyOS4的优化
    • Android 评论at功能的实现
    • 探索抖音禁止录屏
    • 对32位手机崩溃的优化记录
    • GradientDrawable
    • tutorial
    • color
    • webview白屏检测
    • android Resource
    • deeplink技术
    • android-xml
    • ANDROID IPC
    • BottomSheetBehavior研究与思考
    • viewPager
    • android window
    • Android密钥系统
    • compiler
    • Android 端口转发(Forward & Reverse) 的实操与避坑全指南
      • 1. 操作
        • 1.1 示例一:在手机端快速查看电脑端内容
        • 1.2 示例二:用 Python 脚本实现“动态文件列表”接口
        • 1.3 手机使用电脑的代理工具
        • 1.3.1 在未连接任何wifi的情况下设置代理
      • 二、问题记录
        • 1. 端口幽灵冲突:多进程监听同一端口
      • 三、 专家级进阶建议
    • 提升UI加载速度的几点思考
    • Android零耗时首帧体验
    • jsbridge
    • retrofit动态代理设计
    • gif与属性动画的对比
  • kotlin

  • 《android》
  • other
Jacky
2026-04-29
目录

Android 端口转发(Forward & Reverse) 的实操与避坑全指南

我的 Android 系统镜像精简得非常彻底,常用的网络调试工具(nc, python, telnetd)都没有内置。本次使用反向代理进行演示

# 1. 操作

# 1.1 示例一:在手机端快速查看电脑端内容

  1. 电脑端(服务端)

    #  启用 python 内置模块 http.server 监听端口 9999
    python3 -m http.server 9999
    
    1
    2
  2. 建立反向转发 (Reverse):

    adb reverse tcp:8888 tcp:9999
    
    1
  3. 手机端(客户端)测试: 使用手机自带的 curl(如果也没有,直接用浏览器访问 http://localhost:8888):

    adb shell "curl http://localhost:8888"
    
    1

    预期结果:手机成功获取到了你电脑目录下分析脚本的文件列表,可以预览下载等操作。

# 1.2 示例二:用 Python 脚本实现“动态文件列表”接口

  1. 在电脑端创建脚本 server.py:

    import http.server
    import socketserver
    import os
    
    PORT = 9999
    
    class ListFileHandler(http.server.SimpleHTTPRequestHandler):
        def list_directory(self, path):
            # 强制列出当前目录下的所有 .csv 或 .py 文件
            files = [f for f in os.listdir(path) if not f.startswith('.')]
            file_list_str = "\n".join(files)
            self.send_response(200)
            self.send_header("Content-type", "text/plain; charset=utf-8")
            self.end_headers()
            self.wfile.write(f"当前目录下的文件有:\n{file_list_str}".encode('utf-8'))
            return None
    
    with socketserver.TCPServer(("", PORT), ListFileHandler) as httpd:
        print(f"Serving at port {PORT}")
        httpd.serve_forever()
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
  2. 运行此脚本. python server.py

  3. 开启反向转发 adb reverse tcp:8888 tcp:9999

  4. 在手机端访问: 127.0.0.1:8888, 你会直接在手机终端看到清晰的文件名列表

# 1.3 手机使用电脑的代理工具

当手机没有网络,这里代理不通的时候。 可以让手机访问这个端口来翻墙或上网

  1. 建立反向代理隧道: 在电脑终端执行,将手机内部的 7890 映射到电脑的 7890:

    adb reverse tcp:7890 tcp:7890
    
    1
  2. 手机端配置(以 shell 为例): 在 adb shell 中设置环境变量,让命令行工具(如 curl)走这个代理:

    export http_proxy=http://localhost:7890
    export https_proxy=http://localhost:7890
    
    1
    2
  3. 测试联网:

    adb shell "curl -I https://www.google.com"
    
    1
  4. 全局上网(针对手机 App): 如果你希望手机里的 App 也能上网,需要在手机的 WiFi 设置 -> 修改网络 -> 代理 -> 手动 中,将代理服务器主机名设为 127.0.0.1,端口设为 7890。由于你执行了 reverse,手机访问自己的 127.0.0.1:7890 实际上就是在访问电脑。

⚠️ 关键避坑与技术细节

  1. DNS 解析问题(大坑): 这是最容易失败的地方。即便你转发了 TCP 端口,手机可能依然无法解析域名(DNS)。

    • 对策:在手机的代理设置里,确保代理协议支持远程 DNS 解析(如 SOCKS5),或者直接在 curl 时使用 IP 地址测试。
  2. 代理工具设置: 在电脑端的代理软件中,务必开启 “允许局域网连接” (Allow LAN)。虽然 adb reverse 看起来是 localhost 访问,但某些代理软件的防火墙策略会拦截非本进程发起的请求。

  3. HTTPS 证书: 如果你在电脑上使用了自签名证书的抓包工具(如 Charles 或 Fiddler),手机端访问 HTTPS 网站时会报证书错误,需要在手机上安装对应的根证书。

清理工作:恢复手机自己的上网功能

  1. 撤销 ADB 端口映射(电脑端操作)
    # 停止所有的反向代理(针对 reverse)
    adb reverse --remove-all
    
    # 停止所有的正向转发(针对 forward,如果有的话)
    adb forward --remove-all
    
    1
    2
    3
    4
    5
  2. 清除手机系统代理设置(手机端操作 设置 -> WLAN -> 点击当前连接的 WiFi 详情/修改网络 -> 代理 -> 改为“无”。
  3. 清理 Shell 环境变量(adb shell 操作)
    # 或者手动 unset 掉变量
    unset http_proxy
    unset https_proxy
    
    1
    2
    3
  4. 清理进阶: 追求高效,可以把清理动作写成一个简单的脚本或 zsh alias,每次调试完“一键恢复” alias adb_clean='adb reverse --remove-all && adb forward --remove-all && echo "ADB tunnels cleared."'

# 1.3.1 在未连接任何wifi的情况下设置代理

android 系统设计上的一个原生限制:系统级的代理设置界面是与具体的 WiFi 热点(SSID)绑定的。此方案实际测试下来感觉还是有点问题,作为参考记录下

对于这种需要在断网/无 WiFi 场景下通过 adb reverse 共享电脑网络的需求, 可以采用以下几种“非常规”手段来绕过这个 UI 限制:

1. 命令行强制注入(无需 WiFi,需 Root 或开发者权限)

是最硬核、最有效的方法。Android 的系统代理配置实际上存储在 Settings 数据库中。你可以直接通过 adb shell 修改它:

  • 设置全局代理(立即生效):
    settings put global http_proxy 127.0.0.1:7890
    settings put global https_proxy 127.0.0.1:7890
    settings put global all_proxy 127.0.0.1:7890
    
    1
    2
    3
  • 移除代理(恢复时必做):
    settings delete global http_proxy
    settings delete global https_proxy
    settings delete global all_proxy
    
    1
    2
    3
    注:这种方式是系统级的,不管你连不连 WiFi,所有的流量都会尝试走这个代理。

# 二、问题记录

# 1. 端口幽灵冲突:多进程监听同一端口

  • 现象:开启了 Python 服务监听 9999,结果 curl 出来的是 Node 博客的内容,且 Python 端没报错。
  • 深层原因:
    • IPv4 vs IPv6:一个进程占用了 IPv4,另一个占用了 IPv6,系统允许共存。
    • 内核优先级:内核会根据地址具体程度或监听顺序分配流量,导致请求被 Node 进程“拦截”。
  • 对策:养成使用 lsof -i :端口号 确认真实 PID 的习惯。

# 三、 专家级进阶建议

  1. 清理习惯:

端口映射是持久生效的(只要不拔线)。为了避免占用系统资源或导致后续冲突,演示/调试结束后养成清理习惯:

adb reverse --remove-all
adb forward --remove-all
1
2
  1. 无线调试同样适用: 如果你开启了 adb connect [IP] 无线连接,上述所有 forward 和 reverse 命令依然有效,这在调试 Redmi 7A/8A 等特定机型 的渲染性能时,可以摆脱数据线的物理束缚。

  2. 配合 Python 自动化: 既然你擅长编写 Python 脚本,可以将这些命令封装进你的 AkShareAna 分析流程中。例如:脚本分析完 BYD 财务报表后,自动执行 adb reverse,然后通过 os.system 启动浏览器展示结果,实现“分析-传输-预览”全自动化。

#adb
上次更新: 2026/04/29, 20:42:51
compiler
提升UI加载速度的几点思考

← compiler 提升UI加载速度的几点思考→

最近更新
01
VisiData 终极生存指南
04-27
02
macOS 定时任务实现:Git 仓库状态自动同步方案
04-26
03
fzf
04-11
更多文章>
Theme by Vdoing | Copyright © 2019-2026 Jacky | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式