跨网段使用Reveal调试

Reveal是iOS开发中经常用到的调试利器。在公司使用中遇到了无法找到设备的问题。因为Reveal使用Bonjour来完成设备服务发现,但是在公司内手机和Mac常常不在同一个网段内,会出现无法找到设备的问题。花了些时间来解决这个问题,挺有意思的。

Reveal通信方法

想了解手机上Reveal的库与Mac上客户端的通信方法,找到了一篇官方帮助文档很有价值:Bonjour Debuging。这里我们知道了服务发现用的是Bonjour,下面是一些有用的方法:

获取周围所有reveal服务列表


dns-sd -B _reveal._tcp local


运行之后会列出一些服务列表。在某一条信息中,拿到实例名称,可以根据实例名称查询主机名与端口号。reveal同时还会返回一些设备信息、应用信息与reveal协议版本号。


dns-sd -L Reveal--618e4d6a _reveal._tcp.


Reveal使用的是HTTP协议,将从Bonjour拿到的主机名与端口拼接起来,就可以查看Reveal的协议,并未加密。


http://johns-5s.local.:65152/application


通过抓包分析Reveal协议使用的URL除了/Application外还有/objects/188?subviews=0

打通网段

请求转发

想要打通网段,想到的第一个方法是写代理应用来转发。首先是通过Bonjour来发布一个Reveal服务,使用NSNetService来实现。我发现Reveal设备列表里显示的应用和设备信息并不通过Reveal自己的HTTP接口获取,而是通过Bonjour来提供的。这些信息可以通过- (BOOL)setTXTRecordData:(NSData *)recordData;方法来设置。可以通过+ (NSData *)dataFromTXTRecordDictionary:(NSDictionary *)txtDictionary方法将一个字典转换成这里要用的NSData。

建立NSNetService需要提供一个端口。起初对Bonjour的作用并不是很理解。当时随便写了一个。在使用这个端口进行HTTP请求的时候,在NSNetService中并不能找到响应的方法。直到阅读了CocoaHTTPServer的代码后,才明白Bonjour只是帮你把服务公布出去,并不涉及服务建立。

因此使用CocoaHTTPServer建立HTTP服务来响应请求,将一些Bonjour用到的信息设置进去,CocoaHTTPServer会自动帮你发布。这个方法是行得通的,Reveal会正常加载。过程中唯一遇到的问题是Reveal应用会判断HTTP头的Content-Type,写成application/json; charset=utf-8

接下来需要做的是拿到设备的主机名与端口,转发请求。在做这些事情之前,我想到了另一个方法。

Bonjour转发

忽然想到网络本身是可以通信的,只是Bonjour没能跨网段。只要在本地建立一个Bonjour服务,并在收到查询的时候将设备的IP、端口等信息返回就可以了。这件事情甚至在命令行就足以完成:


dns-sd -P Reveal--0a260b700000 _reveal._tcp local 50757 xx.xx.xx.xx xx.xx.xx.xx  "devLocalModel=iPhone" "isSim=false" "devName=Proxy John's 5S" "appName=RevealIt" "devSysVer=9.0" "devSysName=iPhone OS" "appBundleId=com.johnwong.RevealIt" "protoVer=18"


为了防止这个服务与设备原有的服务冲突,在实例名称后添加了4个0,主机名也使用IP地址。

接下来需要做的就是获取设备中一些信息用来建立Bonjour服务。建立了项目Reveal Proxy来做这些事情,只需要将Bonjour目录下代码加入项目。加入后将会打印出需要在命令行输入的命令,就可以在Reveal中调试设备了。


Bonjour
├── JWBonjour.h
├── JWBonjour.m
├── JWBonjourManager.h
├── JWBonjourManager.m
├── JWBonjourUtil.h
└── JWBonjourUtil.m
2015-08-13 17:13:33.104 RevealIt[12647:562110] Bonjour Run:
dns-sd -P Reveal--0a260b700000 _reveal._tcp local 50757 xx.xx.xx.xx xx.xx.xx.xx  "devLocalModel=iPhone" "isSim=false" "devName=Proxy John's 5S" "appName=RevealIt" "devSysVer=9.0" "devSysName=iPhone OS" "appBundleId=com.johnwong.RevealIt" "protoVer=18"


最最后想说的是,解决了这个问题后,发现目前手机与Mac不在一个网段,也能发现设备。也就是说搞完了发现并没有什么用处。唉,有空再看看Reveal的协议,看看能做点什么。

上一篇:深入理解并行编程-分割和同步设计(一)


下一篇:SQL Server判断数据库、表、存储过程、函数是否存在