蓝牙是一种无线通讯协议,主要用于短程和低耗电的设备,其有效通讯范围约30ft,传输速度为1Mb/s.在蓝牙4.0以后将通信模式分为高速和低速类型.高速类型是传统蓝牙,在iOS中高速蓝牙通信开发可以通过GameKit实现.低俗类型成为低功耗蓝牙,可以连接一些量测型传感器,可以通过CoreBluetooth.frameWork实现.
GameKit
GameKit开发采用的网络结构通常是对等结构网络.对等结构网络也叫点对点网络,每个节点之间是对等的.对等结构网络分布范围比较小,通常在一间办公室或一个家庭内,因此它非常适合于iOS设备间的网络通信,网络链路层是由蓝牙和WIFI实现.
对等结构网络是苹果AdHoc网络的一种,在小空间里构建无线网络的解决方案.苹果在GameKit框架中提供了开发这种网络API
连接一旦创建,会话也就建立起来.会话是与网络中运行应用的对等点对应的,每一对等点都会有一个PeerID作为标示区别彼此,可以指定也可以系统分配.在彼此发现方面,GameKit采用Banjour发现服务,这些对于开发人员是不可见的,不用关心他们的细节问题.
为了能够发现彼此,会话可以配置为:"服务器"(发布服务),"客户端"(搜索服务)和"对等点"(发布和搜索服务)三种类型
基于蓝牙连接的对等网络在数据传输时,传输的距离有限,另外GameKit对于传输的数据量也有一定的限制,数据量最大不能超过87KB,处于性能考虑传输数据不要超过1000B,如果超过,分隔成几个数据包传输.
基于蓝牙对等网络通信就是使用GameKit中的GKSession,GKSessionDelegate,GKPeerPickerController,GKPeerPickerControllerDelegate来实现.开发过程分为3个步骤:连接,发送数据和接收数据
具体的连接过程是
1.创建GKPeerPickerController对象
2.设置GKPeerPickerController的委托为self
3.成功回调委托方法- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
4.获得Session对象
5.设置Session的委托为self
6.Session状态变化回调委托方法- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state
我根据源码做了一点小修改
- (void)viewDidLoad { [super viewDidLoad]; [self clearUI]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } -(void) clearUI { [_btnConnect setTitle:@"连接" forState:UIControlStateNormal]; [_btnClick setEnabled:NO]; _lblPlayer2.text = @"0"; _lblPlayer1.text = @"0"; } - (void)viewDidUnload { [self setBtnConnect:nil]; [self setLblPlayer1:nil]; [self setLblPlayer2:nil]; [self setBtnClick:nil]; [super viewDidUnload]; } - (IBAction)onClick:(id)sender { _lblPlayer1.text = [NSString stringWithFormat:@"我发送了:%@",self.sendTextField.text]; NSDictionary *str = @{@"code":@(0),@"count":self.sendTextField.text}; NSString *str2 = [str JSONString]; NSData* data = [str2 dataUsingEncoding: NSUTF8StringEncoding]; if (_session) { [_session sendDataToAllPeers:data withDataMode:GKSendDataReliable error:nil]; } } - (IBAction)connect:(id)sender { _picker = [[GKPeerPickerController alloc] init]; _picker.delegate = self; _picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby; [_picker show]; } #pragma mark--GKPeerPickerControllerDelegate - (void)peerPickerController:(GKPeerPickerController *)pk didConnectPeer:(NSString *)peerID toSession:(GKSession *) session { NSLog(@"建立连接"); _session = session; _session.delegate = self; [_session setDataReceiveHandler:self withContext:nil]; _picker.delegate = nil; [_picker dismiss]; [_btnClick setEnabled:YES]; [_btnConnect setTitle:@"断开连接" forState:UIControlStateNormal]; } - (void)peerPickerControllerDidCancel:(GKPeerPickerController *)pk { NSLog(@"取消连接"); _picker.delegate = nil; } #pragma mark--GKSessionDelegate - (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state { if (state == GKPeerStateConnected) { NSLog(@"connected"); [_btnConnect setTitle:@"断开连接" forState:UIControlStateNormal]; [_btnClick setEnabled:YES]; } else if (state == GKPeerStateDisconnected) { NSLog(@"disconnected"); [self clearUI]; } } - (void)session:(GKSession *)session didFailWithError:(NSError *)error { NSLog(@"error %@",[error description]); } - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:(GKSession *)session context:(void *)context { id jsonObj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; NSNumber *codeObj = [jsonObj objectForKey:@"code"]; if ([codeObj intValue]== GAMING) { NSString * countObj= [jsonObj objectForKey:@"count"]; _lblPlayer2.text = [NSString stringWithFormat:@"对方发送了:%@",countObj]; } else if ([codeObj intValue]== GAMED) { [self clearUI]; } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self.sendTextField resignFirstResponder]; }