MultipeerConnectivity.frameworkiOS 7.0OS X 10.10
可以看到基於MC可以做到電腦與手機的通信。 了解了其能力與SDK相關信息後,下面我們看看工作流程: 使設備可被發現--->浏覽設備,建立連接--->傳輸數據 。 關於使用大家可以看看參考資源與 MCDemo, 這裡只是做一個代碼導讀。
-(void)setupPeerAndSessionWithDisplayName:(NSString *)displayName{ _peerID = [[MCPeerID alloc] initWithDisplayName:displayName]; _session = [[MCSession alloc] initWithPeer:_peerID]; _session.delegate = self; }
-(void)advertiseSelf:(BOOL)shouldAdvertise{ if (shouldAdvertise) { _advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:@chat-files discoveryInfo:nil session:_session]; [_advertiser start]; } else{ [_advertiser stop]; _advertiser = nil; } }
-(void)setupMCBrowser{ _browser = [[MCBrowserViewController alloc] initWithServiceType:@chat-files session:_session]; }
-(void)sendMyMessage{ NSData *dataToSend = [_txtMessage.text dataUsingEncoding:NSUTF8StringEncoding]; NSArray *allPeers = _appDelegate.mcManager.session.connectedPeers; NSError *error; [_appDelegate.mcManager.session sendData:dataToSend toPeers:allPeers withMode:MCSessionSendDataReliable error:&error]; if (error) { NSLog(@%@, [error localizedDescription]); } [_tvChat setText:[_tvChat.text stringByAppendingString:[NSString stringWithFormat:@I wrote: %@ , _txtMessage.text]]]; [_txtMessage setText:@]; [_txtMessage resignFirstResponder]; }
-(void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID{ NSDictionary *dict = @{@data: data, @peerID: peerID }; [[NSNotificationCenter defaultCenter] postNotificationName:@MCDidReceiveDataNotification object:nil userInfo:dict]; }
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{ if (buttonIndex != [[_appDelegate.mcManager.session connectedPeers] count]) { NSString *filePath = [_documentsDirectory stringByAppendingPathComponent:_selectedFile]; NSString *modifiedName = [NSString stringWithFormat:@%@_%@, _appDelegate.mcManager.peerID.displayName, _selectedFile]; NSURL *resourceURL = [NSURL fileURLWithPath:filePath]; dispatch_async(dispatch_get_main_queue(), ^{ NSProgress *progress = [_appDelegate.mcManager.session sendResourceAtURL:resourceURL withName:modifiedName toPeer:[[_appDelegate.mcManager.session connectedPeers] objectAtIndex:buttonIndex] withCompletionHandler:^(NSError *error) { if (error) { NSLog(@Error: %@, [error localizedDescription]); } else{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@MCDemo message:@File was successfully sent. delegate:self cancelButtonTitle:nil otherButtonTitles:@Great!, nil]; [alert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:NO]; [_arrFiles replaceObjectAtIndex:_selectedRow withObject:_selectedFile]; [_tblFiles performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; } }]; //NSLog(@*** %f, progress.fractionCompleted); [progress addObserver:self forKeyPath:@fractionCompleted options:NSKeyValueObservingOptionNew context:nil]; }); } }
-(void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress{ NSDictionary *dict = @{@resourceName : resourceName, @peerID : peerID, @progress : progress }; [[NSNotificationCenter defaultCenter] postNotificationName:@MCDidStartReceivingResourceNotification object:nil userInfo:dict]; dispatch_async(dispatch_get_main_queue(), ^{ [progress addObserver:self forKeyPath:@fractionCompleted options:NSKeyValueObservingOptionNew context:nil]; }); }
void * -[MCPeerID initWithDisplayName:](void * self, void * _cmd, void * arg2) { STK33 = r5; STK35 = r7; sp = sp - 0x28; r5 = arg2; arg_20 = self; arg_24 = *0x568f0; r6 = [[&arg_20 super] init]; if (r6 != 0x0) { if ((r5 == 0x0) || ([r5 length] == 0x0)) { r0 = [r6 class]; r0 = NSStringFromClass(r0); var_0 = r0; [NSException raise:*_NSInvalidArgumentException format:@Invalid displayName passed to %@]; } else { if ([r5 lengthOfBytesUsingEncoding:0x4] >= 0x40) { r0 = [r6 class]; r0 = NSStringFromClass(r0); var_0 = r0; [NSException raise:*_NSInvalidArgumentException format:@Invalid displayName passed to %@]; } } arg_8 = r6; arg_C = r5; r8 = CFUUIDCreate(*_kCFAllocatorDefault); CFUUIDGetUUIDBytes(&arg_10); r11 = (arg_1C ^ arg_14) << 0x18 | (arg_1C ^ arg_14) & 0xff00 | 0xff00 & (arg_1C ^ arg_14) | arg_1C ^ arg_14; r10 = 0xff00 & (arg_10 ^ arg_18) | ((arg_10 ^ arg_18) & 0xff00) << 0x8 | arg_10 ^ arg_18 | arg_10 ^ arg_18; r5 = _makebase36string(r11, r10); if (*_gVRTraceErrorLogLevel < 0x6) { asm{ strd r4, r5, [sp] }; VRTracePrint_(); } else { if (*(int8_t *)_gVRTraceModuleFilterEnabled != 0x0) { asm{ strd r4, r5, [sp] }; VRTracePrint_(); } } r4 = [NSString stringWithUTF8String:r5]; free(r5); CFRelease(r8); r0 = [MCPeerIDInternal alloc]; var_0 = r10; arg_4 = arg_C; r0 = [r0 initWithIDString:r4 pid64:r11 displayName:STK-1]; r6 = arg_8; r6->_internal = r0; } r0 = r6; Pop(); Pop(); Pop(); return r0; } [[MCPeerIDInternal alloc] initWithIDString:_makebase36string(...) pid64:r11 displayName:STK-1]
-- Apple Mutipeer Connectivity Custom DTLS Protocl -- cache globals to local for speed. local format = string.format local tostring = tostring local tonumber = tonumber local sqrt = math.sqrt local pairs = pairs -- wireshark API globals local Pref = Pref local Proto = Proto local ProtoField = ProtoField local DissectorTable = DissectorTable local Dissector = Dissector local ByteArray = ByteArray local PI_MALFORMED = PI_MALFORMED local PI_ERROR = PI_ERROR -- dissectors local dtls_dissector = Dissector.get(dtls) apple_mcdtls_proto = Proto(apple_mcDTLS, Apple Multipeer Connectivity DTLS, Apple Multipeer Connectivity DTLS Protocol) function apple_mcdtls_proto.dissector(buffer, pinfo, tree) local mctype = buffer(0, 1):uint() if mctype == 208 then pinfo.cols.protocol = AppleMCDTLS pinfo.cols.info = Apple MC DTLS Payload Data local subtree = tree:add(apple_mcdtls_proto, buffer(), Apple MC DTLS Protocol) subtree:add(buffer(0, 1),Type: .. buffer(0, 1):uint()) local size = buffer:len() subtree:add(buffer(1, size - 1), Data: .. tostring(buffer)) dtls_dissector:call(buffer(1):tvb(), pinfo, tree) end end local function unregister_udp_port_range(start_port, end_port) if not start_port or start_port <= 0 or not end_port or end_port <= 0 then return end udp_port_table = DissectorTable.get(udp.port) for port = start_port,end_port do udp_port_table:remove(port, apple_mcdtls_proto) end end local function register_udp_port_range(start_port, end_port) if not start_port or start_port <= 0 or not end_port or end_port <= 0 then return end udp_port_table = DissectorTable.get(udp.port) for port = start_port,end_port do udp_port_table:add(port, apple_mcdtls_proto) end end register_udp_port_range(16400, 16499)