本篇主要介绍两个部分:
- ADB的端口映射
- LocalServerSocket
文章目录
- 1. ADB端口映射
- 1.1 adb forward
- 1.2 adb reverse
- 1.3 其他相关命令
- 2. LocalServerSocket
- 3. 二者关系
- 3.1 localabstract
- 4. 总结
1. ADB端口映射
端口映射的应用的场景很多,尤其是PC和手机需要进行通信的时候,利用端口转发可以很方便地让手机访问PC的服务,亦或是反过来。
ADB提供了两个非常实用的命令用来实现端口转发,分别是:adb forward
和 adb reverse
。
1.1 adb forward
将PC的端口映射到手机的端口,比如adb forward tcp:13000 tcp:15000
,就是将PC的13000
端口映射到手机的15000
端口。
注意,是PC端口在前,手机端口在后,即adb forward <LOCAL> <REMOTE>
。
这个通常用于PC访问手机侧服务的场景,流程是这样的:
- 手机侧创建server服务,比如通过
ServerSocket
类创建一个服务等待连接; - 执行
adb forward tcp:13000 tcp:15000
,这样adb会自动在PC创建一个端口13000
的服务等待连接。通过命令netstat -a | grep 13000
,可以看到; - PC侧创建client,比如用python写一个简易的Socket客户端,连接端口
13000
,IP就是localhost
; - 这样PC就和手机的
15000
端口连接上了(这里就是端口映射起作用了,将PC的13000端口映射到手机的15000端口,数据都转发过去了),然后PC可以访问手机的服务了。
1.2 adb reverse
这个命令和forward是反过来的,是将手机的端口映射到PC的端口(也可以说是反向代理)。比如adb reverse tcp:13000 tcp:15000
,就是将手机的13000
端口映射到PC的15000
端口。
注意,和forward不一样,reverse命令是手机端口在前,PC端口在后,即adb reverse <REMOTE> <LOCAL>
。
这个通常用于手机访问PC侧服务的场景,流程是这样的:
- PC创建server服务,端口是
15000
,并等待连接; - 执行
adb reverse tcp:13000 tcp:15000
,这样adb会自动在手机侧创建一个端口13000
的服务,并等待连接; - 手机侧创建client,连接端口
13000
; - 这样手机就和PC的
15000
端口连接上了(这里就是端口映射起作用了,将手机的13000端口映射到PC的15000端口,数据都转发过去了),然后手机访问PC侧的服务了。
1.3 其他相关命令
-
adb forward --list
- 列举出当前所有的映射 -
adb forward --remove LOCAL
- 删除某个映射 -
adb forward --remove-all
- 全删
adb reverse的命令类似,就不一一列举了。
2. LocalServerSocket
LocalServerSocket
是Android SDK中的一个类,用来创建一个Socket,只不过这个Socket是Unix域套接字(Unix Domain socket),从类的描述也能看出:
Unix域套接字用于同一台设备的进程间通信(IPC)。通常我们创建一个普通Socket时,需要传入端口号,但创建Unix域套接字,需要指定的的是一个字符串或者文件描述符。
LocalServerSocket
创建的socket类型是LocalSocket
,通过LocalSocket
可以获取到一个文件描述符FileDescriptor
,通过对该文件描述符进行读写就可以传输数据了。
/* Server端 */
LocalServerSocket localServerSocket = new LocalServerSocket("my-domain-socket");
LocalSocket localSocket = localServerSocket.accept();
FileDescriptor fd = localSocket.getFileDescriptor();
/* Client端 */
LocalSocket localSocket = new LocalSocket();
localSocket.connect(new LocalSocketAddress("my-domain-socket"));
FileDescriptor fd = localSocket.getFileDescriptor();
/* 对fd进行读写 */
Os.write(fd);
Os.read(fd);
3. 二者关系
ADB端口映射和LocalServerSocket看似没什么关系,但为什么要放在一起介绍呢?其实还是要归结到端口映射这一块。
前面小节中我们是将一个端口映射到另一个端口,但实际上ADB还支持将端口映射到Unix域套接字上。这样就为我们在一些场景提供了便利,比如我们不知道对端端口号的情况:现实场景中创建服务,往往考虑到端口占用等情况,端口号不一定是固定的。这样我们在执行(尤其是代码化执行)adb forward
命令时进行端口映射的时候,是无法知道映射哪个端口的。
有了Unix域套接字映射就提供了可能,双方约定好一个固定的名称即可。
3.1 localabstract
前文我们使用映射命令是adb forward tcp:13000 tcp:15000
或 adb reverse tcp:13000 tcp:15000
,如果映射Unix域套接字,只需要变成:
adb forward tcp:13000 localabstract:my-domain-socket
adb reverse localabstract:my-domain-socket tcp:13000
使用localabstract
,这样就把PC的端口映射到了手机侧的Unix域套接字上。结合前文的示例代码,创建LocalServerSocket的服务端或客户端,就可以PC进行连接并通信了。
4. 总结
本文不长,主要介绍了ADB里的端口映射功能,主要因为使用场景广泛,所以比较实用。比如PC上的手机管理软件、网络调试工具Stetho、 Scrcpy手机投屏等,内部都有用到ADB端口映射,至于正向还是反向要具体的业务需要。同时结合LocalServerSocket
可以在无法知道端口号的场景下通过Unix域套接字进行映射,进一步降低了局限,拓宽了使用场景。