端口转发

Posted by Codeboy on February 29, 2020

前言

随着移动App的庞大,自动化测试越来越重要,常见的移动端测试框架有很多, Appium 是比较流行的一个 ,在电脑端安装 Appium Server , 将测试手机连接该电脑后,可以通过api/http请求操作手机。最近尝试了下自动化测试,整体结构图如下:

每一台PC连接一些手机,控制中心(Control Center)负责将指令下发给PC上的 Appium Server,最终应用到手机上。这种结构也方便扩展,可以在更多的PC上安装 Appium Server ,连接手机,在控制中心上配置PC后,接入更多的设备,使用控制中心中预设的命令进行自动化测试。

问题

在一个局域网中的控制中心和PC没有问题,但是为了能够使控制中心更加的灵活,希望能够将其部署在云端。

Appium Server通过发送http请求进行设备的控制,默认的格式如下:

http://0.0.0.0:4723/api/path

局域网内的机器相互访问没有问题,但是控制中心部署到云端,不能直接请求到PC机,怎么才能使云端主机是能够访问到内网主机的服务呢?

解决方案

笔者之前有篇文章介绍到ssh,SSH正向与反向代理,如果在云端主机可以操作的境况下,使用ssh进行端口映射即可,将远端主机端口映射到本机指定端口,例如将远端10000端口映射到本地4723端口,配置后,访问远端主机10000端口,就相当于访问本地端口。

由于牵扯到云端主机登陆身份验证,本文换另一种方式解决,整体原理相同,本地主机和云端主机建立一条通道,由内网主机发起请求,通过建立长链接,后续命令通过长链接通道进行转发。

如果仅需将本机的端口A转发到端口B,可以看作是一次短链接,不需要维护长链接通道。

实现步骤

1. 建立长链接(socket通道)

使用标准java socket模式,这里不再介绍。

2. 心跳

socket通道在一段时间没有消息的传递将会关闭,需要定时进行心跳包的发送维持活性。

3. 转发命令

记云端主机为A,运行socket server, 提供服务的本地主机为B,运行socket client,请求服务的设备为C。

  • C发送http请求给A;
  • A接收到请求后,将请求头部解析后,添加特殊前缀标示(为了区分心跳),写入到socket通道给B;
  • B收到后,发送对应的请求给预设定的服务端口(提供服务,如4723 appium端口);
  • B获取到请求的response,将其通过socket通道反向写回给A;
  • A收到后,将其原样返回给请求发起方A;

这样完成了在C不能访问B的场景下,获取了B的服务信息。

代码

https://github.com/androiddevelop/java-example/tree/master/src/main/java/me/codeboy/example/portforward

小结

端口转发在很多场景下都有使用,根据用途分为正向代理反向代理 的,本文属于后者,同时本文场景可以和常见的push类比,由于没有很高的请求量,笔者并没有实现并发的请求转发,实现版本的通道中只能在一次转发完成后进行下一次,如果实现并发,需要加入其他信息来进行消息的映射,这里不讨论。

如有任何知识产权、版权问题或理论错误,还请指正。

转载请注明原作者及以上信息。