一、usbmuxd 介紹
usbmuxd 是蘋果的一個(gè)服務(wù),這個(gè)服務(wù)主要用于在USB協(xié)議上實(shí)現(xiàn)多路TCP連接,將USB通信抽象為TCP通信。蘋果的iTunes、Xcode,都直接或間接地用到了這個(gè)服務(wù)。
iTunes使用 usbmux 與 iphone 通信, 它提供了一個(gè)USB - TCP的轉(zhuǎn)換服務(wù), 這個(gè)服務(wù)在Mac端是由/System/Library/PrivateFrameworks/MobileDevice.framework/Resources/usbmuxd提供的, 當(dāng)然, 開機(jī)自動(dòng)啟動(dòng)。
它創(chuàng)建了一個(gè)Unix Domain Socket 在 /var/run/usbmuxd. usbmuxd服務(wù)程序監(jiān)控iPhone在USB口上的連接, 當(dāng)它監(jiān)控到iPhone以用戶模式連接到USB, (相對(duì)的是recovery模式), usbmuxd服務(wù)程序就會(huì)連接到這個(gè)/var/run/usbmuxd的TCP端口, 并開始成為一個(gè)USB - TCP 請(qǐng)求轉(zhuǎn)發(fā)器
那么,如果想編寫個(gè)第三方程序與iphone進(jìn)行通信,實(shí)現(xiàn)類似iTunes的功能, 你的程序可以通過usbmuxd! 建立一個(gè)TCP連接到/var/run/usbmuxd端口, 根據(jù)協(xié)議發(fā)送對(duì)應(yīng)的請(qǐng)求包, usbmuxd服務(wù)會(huì)將請(qǐng)求轉(zhuǎn)發(fā)到USB的iPhone上。
peertalk,一個(gè)基于usbmuxd服務(wù)的開源代碼,可以實(shí)現(xiàn) iPhone 與 Mac 通信。
libimobiledevice,在可以PC端提供usbmuxd服務(wù),實(shí)現(xiàn) iPhone 與 windows 通信。
二、Peertalk 的使用:iPhone 與 Mac 通信
iOS 端
1、創(chuàng)建 channel,監(jiān)聽指定端口
// 創(chuàng)建 channel
PTChannel *channel = [PTChannel channelWithDelegate:self];
// 監(jiān)聽指定端口,PTExampleProtocolIPv4PortNumber自定義端口號(hào)
[channel listenOnPort:PTExampleProtocolIPv4PortNumber IPv4Address:INADDR_LOOPBACK callback:^(NSError *error) {
if (error) { // 創(chuàng)建監(jiān)聽失敗
} else { // 創(chuàng)建監(jiān)聽成功
}
}];
2、實(shí)現(xiàn) Channel 的代理方法
@protocol PTChannelDelegate <NSObject>
@required
// 收到信息
- (void)ioFrameChannel:(PTChannel*)channel didReceiveFrameOfType:(uint32_t)type tag:(uint32_t)tag payload:(PTData*)payload;
@optional
// 收到消息調(diào)用,如回復(fù)NO,則忽略這條消息
- (BOOL)ioFrameChannel:(PTChannel*)channel shouldAcceptFrameOfType:(uint32_t)type tag:(uint32_t)tag payloadSize:(uint32_t)payloadSize;
// 出錯(cuò)回調(diào)
- (void)ioFrameChannel:(PTChannel*)channel didEndWithError:(NSError*)error;
// 連接成功回調(diào)
- (void)ioFrameChannel:(PTChannel*)channel didAcceptConnection:(PTChannel*)otherChannel fromAddress:(PTAddress*)address;
@end
3、連接成功后,會(huì)發(fā)送設(shè)備信息
Mac 端
1、監(jiān)聽USB設(shè)備的連接/斷開
// 開始監(jiān)聽設(shè)備的連接與斷開
- (void)startListeningForDevices {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
// 監(jiān)聽設(shè)備連接
[nc addObserverForName:PTUSBDeviceDidAttachNotification object:PTUSBHub.sharedHub queue:nil usingBlock:^(NSNotification *note) {
NSNumber *deviceID = [note.userInfo objectForKey:@"DeviceID"];
dispatch_async(notConnectedQueue_, ^{
if (!connectingToDeviceID_ || ![deviceID isEqualToNumber:connectingToDeviceID_]) {
// 斷開現(xiàn)有連接
[self disconnectFromCurrentChannel];
connectingToDeviceID_ = deviceID;
connectedDeviceProperties_ = [note.userInfo objectForKey:@"Properties"];
// 重新連接
[self enqueueConnectToUSBDevice];
}
});
}];
// 監(jiān)聽設(shè)備斷開
[nc addObserverForName:PTUSBDeviceDidDetachNotification object:PTUSBHub.sharedHub queue:nil usingBlock:^(NSNotification *note) {
NSNumber *deviceID = [note.userInfo objectForKey:@"DeviceID"];
if ([connectingToDeviceID_ isEqualToNumber:deviceID]) {
connectedDeviceProperties_ = nil;
connectingToDeviceID_ = nil;
if (connectedChannel_) { // 關(guān)閉連接通道
[connectedChannel_ close];
}
}
}];
}
2、連接設(shè)備
// 連接設(shè)備
- (void)connectToLocalIPv4Port {
// 創(chuàng)建通道,設(shè)置代理
PTChannel *channel = [PTChannel channelWithDelegate:self];
channel.userInfo = [NSString stringWithFormat:@"127.0.0.1:%d", PTExampleProtocolIPv4PortNumber];
// 連接指定端口地址,與iOS端設(shè)置保持一致
[channel connectToPort:PTExampleProtocolIPv4PortNumber IPv4Address:INADDR_LOOPBACK callback:^(NSError *error, PTAddress *address) {
if (error) { // 連接失敗
} else { // 連接成功
}
}];
}
3、連接成功會(huì),會(huì)收發(fā)送 ping、pong 心跳數(shù)據(jù)
三、libimobiledevice、Peertalk 的使用:iPhone 與 windows 通信
1、實(shí)現(xiàn)原理
windows端 通過 libimobiledevice 運(yùn)行 usbmuxd 的多路復(fù)用守護(hù)進(jìn)程,該進(jìn)程的作用是建立本地端口和遠(yuǎn)程端口的轉(zhuǎn)發(fā),實(shí)現(xiàn)usb到tcp的轉(zhuǎn)換服務(wù)
2、安裝服務(wù)
windows端首先要安裝蘋果公司提供的相關(guān)服務(wù),才能實(shí)現(xiàn)通信功能。服務(wù)名稱為:AppleApplicationSupport和AppleMobileDeviceSupport
3、規(guī)定協(xié)議
首先指定 ip地址和端口,端口號(hào)建議大些,以免與蘋果系統(tǒng)應(yīng)用端口重復(fù)。如:127.0.0.1:62345。PC端可以通過端口轉(zhuǎn)發(fā)實(shí)現(xiàn)。
定義相同結(jié)構(gòu)體數(shù)據(jù),以便數(shù)據(jù)的加密、解析。PC端可和Peertalk定義的協(xié)議保持一致。如:
// 數(shù)據(jù)頭結(jié)構(gòu)體
typedef struct _PTFrame {
uint32_t version; // 對(duì)應(yīng)版本
uint32_t type; // 數(shù)據(jù)類型
uint32_t tag; // tag標(biāo)記
uint32_t payloadSize; // 數(shù)據(jù)大小
} PTFrame;
// 數(shù)據(jù)類型
enum {
PTExampleFrameTypeDeviceInfo = 100, // 設(shè)備信息
PTExampleFrameTypeTextMessage = 101, // 文本數(shù)據(jù)
PTExampleFrameTypePing = 102, // Ping
PTExampleFrameTypePong = 103, // Pong
};
4、聯(lián)調(diào)測(cè)試
定好協(xié)議后,指定相同ip地址和端口,進(jìn)行測(cè)試。如連接失敗,可嘗試更換端口號(hào)重試。先調(diào)試連接,然后再收發(fā)數(shù)據(jù),最后進(jìn)行數(shù)據(jù)處理。
參考鏈接1:http://blog.csdn.net/u010343361/article/details/50539401
參考鏈接2:https://github.com/Polyfun/libimobiledevice-windows
參考鏈接3:https://github.com/rsms/peertalk