InputStream无法与BufferReader同时用

​ 前两天客户端这边有一块业务一开始想的是用socket直接跟后端传数据,后来后端觉得基于目前的框架改太麻烦于是协商了一下还是改为HTTP协议,我一想HTTP传过来过我把HTTP的头给忽略掉不就可以了于是直接动手撸了个HTTP服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Socket socket = serverSocket.accept();

BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
LinkedHashMap<String, String> headerFields = new LinkedHashMap<String, String>();
for(String header; (header = r.readLine()) != null && !header.isEmpty();){
//解析HTTP头
...
}

System.out.println(header)

int length = Integer.parseInt(headerFields.get("Content-Length"));
byte[] buffer = new byte[length];
socket.getInputStream().read(buffer);
//处理业务数据
...

OutputStream out = socket.getOutputStream();
out.write("HTTP/1.1 200 OK\r\n".getBytes());
out.write("\r\n".getBytes());
out.write("fuck you\r\n").getBytes());
out.flush();
socket.close();
阅读更多...

使用openstf部署一套内部测试平台

安装环境

安装openstf

  1. sudo docker pull rethinkdb:latest # 拉取rethinkdb 镜像
  2. sudo docker pull sorccu/adb:latest # 拉取android adb 镜像
  3. sudo docker pull devicefarmer/stf:latest #拉取openstf 镜像

部署openstf

openstf部署方式有两种

  1. 集中管理: openstf管理平台所连接的设备在一台机器上

1
2
3
$ docker run -d --name rethinkdb -v /srv/rethinkdb:/data --net host rethinkdb rethinkdb --bind all --cache-size 8192 --http-port 8090
$ docker run -d --name adbd --privileged -v /dev/bus/usb:/dev/bus/usb --net host sorccu/adb:latest
$ docker run -d --name stf --net host devicefarmer/stf stf local --public-ip ${你的ip}
  • 优点:简单快捷适合小规模部署
  • 缺点:不够灵活且单台机器挂载能有限
  1. 分布式管理: openstf提供了provider模式可以用来进行分布式部署

需要准备两台机器A,B 在机器A上部署OpenSTF管理平台

1
2
3
$ docker run -d --name rethinkdb -v /srv/rethinkdb:/data --net host rethinkdb rethinkdb --bind all --cache-size 8192 --http-port 8090
$ docker run -d --name adbd --privileged -v /dev/bus/usb:/dev/bus/usb --net host sorccu/adb:latest
$ docker run -d --name stf --net host devicefarmer/stf stf local --public-ip ${你的ip} --bind-dev-pub="tcp://0.0.0.0:7114" --bind-dev-pull="tcp://0.0.0.0:7116" --allow-remote

注意事项:

1
--bind-dev-pub="tcp://0.0.0.0:7114" --bind-dev-pull="tcp://0.0.0.0:7116"

这行一定要加否则服务将监听在127.0.0.1地址上会导致provider节点无法连接之前没加导致排查了很久

在机器B上部署Provider节点

1
2
$ docker run -d --name adbd --privileged -v /dev/bus/usb:/dev/bus/usb --net host sorccu/adb:latest
$ docker run -d --name stf --net host devicefarmer/stf stf provider --connect-sub tcp://${机器A的IP}:7114 --connect-push tcp://${机器A的IP}:7116 --public-ip ${机器A的IP} --storage-url http://${机器A的IP}:7100/
  • 优点:灵活且理论支持无限拓展连接设备
  • 缺点:配置略微复杂

部署好后访问安装OpenSTF管理平台机器的ip地址加端口7100,如http://192.168.1.1:7100

不通过文件转储直接从adb shell读取stdout数据

通常我们从Android设备中捕获当前UI界面信息使用以下命令:

1
2
adb shell uiautomator dump /sdcard/screen.xml
adb pull /sdcard/screen.xml

在上面的代码块中我们经历了两个步骤

  1. 执行命令结果输出到/sdcard/screen.xml

  2. 拉取设备上的文件

从效率上来看是很慢的那有没有比较快的办法呢? 答案是有的!
我们可以利用/dev/tty设备让它直接输出到stdout上这样就省去文件转储了

1
adb shell uiautomator dump /dev/tty

你满怀期待着等着结果只看到

1
UI hierchary dumped to: /dev/tty

WTF? 这是什么鬼dump出来的信息去哪了?眉头一紧事情好像貌似没有这么简单…
经过一番研究发现我们使用的adb shell会将命令输出发给pty经过一顿骚操作pty把数据搞丢了,所以在新版的adb中引入了一个新的功能exec-out该参数可以将二进制数据直接原封不动的输出。详情请参考

所以只需要将命令改成这样即可:

1
adb exec-out uiautomator dump /dev/tty

如何远程调试一台Android设备

要想跨越公网调试Android设备首先需要解决两个问题:

  1. 如何让adb走tcp通信
  2. 如何从公网连接这台设备

第一个问题:通过tcp调试Android手机

其实adb本身是支持通过tcp协议传输数据的只是可能大部分人从来没用过这个功能,大家可以在终端里面输入adb –help查看,里面有这么几个参数:

1
2
3
4
5
6
7
...
networking:
connect HOST[:PORT] connect to a device via TCP/IP
disconnect [[HOST]:PORT] disconnect from given TCP/IP device, or all
...
usb restart adbd listening on USB
tcpip PORT restart adbd listening on TCP on PORT

connect和disconnect是用来连接一台远程设备或者断开远程设备的,usb和tcpip选项是用来切换手机端adbd守护进程工作模式的我们要用到的就是tcpip这个参数使adbd服务监听在一个特定的网络端口上

在电脑端执行

1
2
3
adb shell ifconfig wlan0 #先查看一下手机wifi的ip地址后续连接的时候会用到
adb tcpip 5555 #将手机切换到tcp模式并在5555端口上监听
adb connect 192.168.1.8:5555 #连接手机对应的ip地址和端口

或者在已root的设备上使用termux软件设置adbd为tcp模式

1
2
3
4
5
6
7
// 持久化设置
# setprop persist.adb.tcp.port 5555
# stop adbd; start adbd
// 一次性设置重启后失效
# setprop service.adb.tcp.port 5555
# stop adbd; start adbd

至此第一个问题已解决

阅读更多...

零成本让你拥有Mac触摸板鼠标

序章

相信用过Mac触摸板鼠标的都被它的丝滑流畅给惊艳过,但是作为一个IT穷屌丝怎么买得起那样高大上的玩意,不过前几天玩VNC的时候倒是有一个很意外发现用起来简直跟Mac鼠标有得一拼.

你需要的东西

  • 手机一台Android/IOS都可以

  • RealVNCAndroid/IOS

我该怎么用

原理很简单就是在电脑上开启vnc server不同操作系统开启方式不一样像Mac和Ubuntu这样本身就是支持VNC的直接在系统设置中打开屏幕共享即可而Windows用户稍微麻烦一些需要额外安装一个tightvnc软件安装过程比较简单在此不讨论自行研究,这样我们直接从手机端通过VNC连过去一个触摸板鼠标就做好了,主要是RealVNC这个软件操作起来比较流畅下面我介绍一下这个软件基本的操作用法:

  1. 鼠标左击 直接点击一下屏幕
  2. 鼠标右击 双指点击一下屏幕
  3. 滚动网页 双指上下搓屏幕
  4. 鼠标选择文字 双击屏幕拖动选择
  5. 鼠标粘贴问题 三指点击屏幕

其他的骚操作可以查看RealVNC的帮助信息

结尾

至此你已经拥有一个流畅的触摸板鼠标了,当然相比于Mac的触摸板鼠标还差很远但是已经有了几分的样子,用手机当触摸板想想也是蛮炫酷的当然有个不好的地方就是手机的画面是和电脑同步的要是有个黑屏只支持操作的模式就好了.

用 Golang 在 Android 上实现代理的几个问题

转自:https://blog.dio.wtf/post/tips-for-golang-proxy-for-android/ 仅供备份

用 Golang 来实现的代理不要太多,像 V2RayBrookClash。一方面得益于 Golang 标准库对于网络编程的支持,另一方面也是由于其便利的交叉编译。如果要在 Android 上用 Golang 实现一套代理方案,还是必须要处理一些问题,或者说是所有的代理方案都要解决的平台特性。

IPC 传递文件描述符

Android 上使用 VpnService 由系统创建一个 TUN 虚拟网卡并接收所有的流量,API 会返回一个 file descriptor,通过这个 FD 可以读取/写入 IP packet。

为了稳定性和性能考虑,我们通常会将代理程序放到一个单独的进程里。但是在 Android 的阉割版 Linux 环境下,子进程是无法访问父进程的 FD。这里就需要用到 Linux 通用的进程间共享 FD 的方案,也就是给 Unix Socket 设置 SCM_RIGHTS 标识,然后用 recvmsgsendmsg 来收发。在 Android 和 Golang 中都有对应的 API。

1
2
public void LocalSocket.setFileDescriptorsForSend (FileDescriptor[] fds)
public FileDescriptor[] LocalSocket.getAncillaryFileDescriptors ()
1
2
3
4
5
6
7
8
9
10
// UnixRights encodes file descriptors into a socket control message
func syscall.UnixRights(fds ...int) []byte
func syscall.Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error)
func syscall.Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error)
// ParseSocketControlMessage parses b as an array of socket control
// messages.
func syscall.ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error)
// ParseUnixRights decodes a socket control message that contains an
// integer array of open file descriptors from another process.
func syscall.ParseUnixRights(m *SocketControlMessage) ([]int, error)
阅读更多...

如何调试Xposed模块不用重启

我想做过Xposed模块开发的一定对调试模块必须要重启手机这个机制不陌生, 拜这个机制所赐每次开发起来苦不堪言。稍微改点东西就需要重启手机少则几十秒要是碰到性能稍差一点的手机几分钟也是有可能的。那我们今天就来好好聊聊怎么才能让修改后的代码即时生效呢?首先要搞清楚这个问题还必须从为什么插件每次修改都要重启手机说起,我们可以通过Xposed开发文档了解到Xposed的工作方式是通过替换/system/bin/app_process这个二进制文件来实现的进程注入的,我们知道app_process是所有进程的启动入口所以xposed替换了这个文件修改了内部执行逻辑优先去加载我们的插件然后再去加载原始的App代码所以才得以实现各种hook,但是问题就出现在加载插件上了,默认的第一次加载插件时系统会在/data/dalvik-cache/创建一份字节码文件给需虚拟机执行,但是因为这个文件只会在第一次加载的时候创建所以当我们修改了插件后再安装这个文件是不会变的,这也就导致我们的改动不会立即生效需要重启手机让系统生成一个新的字节码文件,那肯定有小伙伴会想那我手动把这个字节码文件删了呢?很遗憾我在Android7.0上尝试了一下并未成功原因未知。

阅读更多...
  • Copyrights © 2015-2024 Kaisar
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信