iOS网络编程实践--蓝牙对等网络通信实例讲解-阿里云开发者社区

开发者社区> 关东升> 正文

iOS网络编程实践--蓝牙对等网络通信实例讲解

简介: <p>基于蓝牙对等网络通信就是使用Game Kit中的GKSession、GKSessionDelegate、GKPeerPickerController和GKPeerPickerControllerDelegate来实现。开发过程分为3个步骤:连接、发送数据和接收数据。</p> <p>下面我们通过一个实例介绍一下基于蓝牙对等网络通信过程。用户点击“连接”按钮,建立连接过程中会出现连接对话框,
+关注继续查看

基于蓝牙对等网络通信就是使用Game Kit中的GKSession、GKSessionDelegate、GKPeerPickerController和GKPeerPickerControllerDelegate来实现。开发过程分为3个步骤:连接、发送数据和接收数据。

下面我们通过一个实例介绍一下基于蓝牙对等网络通信过程。用户点击“连接”按钮,建立连接过程中会出现连接对话框,根据具体情况也会弹出其它的对话框。这些都是针对蓝牙对等网络标准对话框,而Wifi对等网络没有标准对话框可以使用,需要开发者自己实现。当两个设备连接好之后,两个玩家就可以连续轻点“点击”按钮,点击的次数会传递给对方,倒计时时间是30秒。

4

1、连接

由于对等网络连接过程有点复杂,贯穿了这些协议和类,我们绘制了连接过程的流程图。

5

下面我们通过代码直接介绍连接流程,其中ViewController.h代码如下:

#import <UIKit/UIKit.h>

#import <GameKit/GameKit.h>

 

#define  GAMING 0          //游戏进行中

#define  GAMED  1          //游戏结束

 

@interface ViewController : UIViewController <GKSessionDelegate, GKPeerPickerControllerDelegate>

{

NSTimer *timer;

}

@property (weak, nonatomic) IBOutlet UILabel *lblTimer;

 

@property (weak, nonatomic) IBOutlet UILabel *lblPlayer2;

@property (weak, nonatomic) IBOutlet UILabel *lblPlayer1;

@property (weak, nonatomic) IBOutlet UIButton *btnConnect;

@property (weak, nonatomic) IBOutlet UIButton *btnClick;

 

@property (nonatomic, strong) GKPeerPickerController *picker;

@property (nonatomic, strong) GKSession *session;

 

- (IBAction)onClick:(id)sender;

- (IBAction)connect:(id)sender;

 

//清除UI画面上的数据

-(void) clearUI;

 

//更新计时器

-(void) updateTimer;

 

@end


使用Game Kit需要引入头文件<GameKit/GameKit.h>,之前需要把GameKit.framework框架添加到工程中。而且定义类的时候需要实现协议GKSessionDelegate和GKPeerPickerControllerDelegate,并且定义GKPeerPickerController类型的属性picker,定义GKSession类型的属性session。

ViewController.m中创建GKPeerPickerController对象的代码如下:

- (IBAction)connect:(id)sender {

_picker = [[GKPeerPickerController alloc] init];

_picker.delegate = self; ①

_picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;  ②

[_picker show];

}


用户点击的连接按钮时,触发connect:方法。在该方法中创建GKPeerPickerController对象。创建完成不要忘记设置GKPeerPickerController委托为self,第②行代码所示。在第③行代码中connectionTypesMask属性是设置对等网络连接类型,其中有两种类型选择:GKPeerPickerConnectionTypeNearby和GKPeerPickerConnectionTypeOnline,GKPeerPickerConnectionTypeNearby用于蓝牙通讯也是默认的通讯方法,GKPeerPickerConnectionTypeOnline用于Wifi通讯的局域网通讯,这种方式麻烦,需要开发人员自己设计UI画面,自己使用Bonjour服务发现管理连接,以及自己编写输入输出流实现通讯。如果给用户一个选择对话框,代码可以如下编写:

_picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby | GKPeerPickerConnectionTypeOnline;

6

其中“在线”就是GKPeerPickerConnectionTypeOnline类型,“附近”就是GKPeerPickerConnectionTypeNearby类型。

连接成功之后回调ViewController.m中的回调委托方法peerPickerController:didConnectPeer:toSession:代码:

- (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];

//开始计时

timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self

selector:@selector(updateTimer)

userInfo:nil repeats:YES]; ⑤

}


上述代码第①行_session = session将委托方法中返回的会话参数赋值给成员变量,这样我们就获得了一个会话对象。这种方式中,会话ID是应用程序的包ID,如果想自己分配会话ID,可以实现下面委托方法,在方法中使用GKSession的构造方法initWithSessionID:displayName: sessionMode:,自己创建会话对象。

- (GKSession *)peerPickerController:(GKPeerPickerController *)picker

sessionForConnectionType:(GKPeerPickerConnectionType)type {

GKSession *session = [[GKSession alloc] initWithSessionID: <自定义SessionID>

displayName:<显示的名字> sessionMode:GKSessionModePeer];

return session;

}


有的时候会话的状态会发生变化,我们要根据状态的变化做一些UI的清理和资源的释放。监测状态变化在委托方法session:peer:didChangeState:中实现,方法代码如下:

- (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];

}

}


其中GKPeerStateConnected常量是已经连接状态,GKPeerStateDisconnected常量是断开连接状态。

2、发送数据

发送数据的代码如下:

- (IBAction)onClick:(id)sender {

int count = [_lblPlayer1.text intValue];

_lblPlayer1.text = [NSString stringWithFormat:@"%i",++count];

NSString *sendStr = [NSString

stringWithFormat:@"{\"code\":%i,\"count\":%i}",GAMING,count]; ①

NSData* data = [sendStr dataUsingEncoding: NSUTF8StringEncoding];

if (_session) {

[_session sendDataToAllPeers:data

withDataMode:GKSendDataReliable  error:nil]; ②

}

}


3、接收数据

为了接收数据首先需要在设置会话时候通过[_session setDataReceiveHandler:self withContext:nil]语句设置接收数据的处理程序是self。这样当数据到达时候就会触发下面的方法特定:

- (void) receiveData:(NSData *)data  fromPeer:(NSString *)peer

inSession:(GKSession *)session  context:(void *)context

{

id jsonObj = [NSJSONSerialization JSONObjectWithData:data

options:NSJSONReadingMutableContainers error:nil];

NSNumber *codeObj = [jsonObj objectForKey:@"code"];

if ([codeObj intValue]== GAMING) {

NSNumber * countObj= [jsonObj objectForKey:@"count"];

_lblPlayer2.text = [NSString stringWithFormat:@"%@",countObj];

} else if ([codeObj intValue]== GAMED) {

[self clearUI];

}

}


上面的代码是接收到数据之后,进行JSON解码,取出游戏状态和点击次数。

主要的程序代码就是这些,根据具体的业务情况还可以能有所变化,读者可以下载完整代码在两台之间设备或是一个设备一个模拟器之间进行测试。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
计算机基础1 | 学习笔记
快速学习计算机基础1。
7 0
计算机基础2 | 学习笔记
快速学习计算机基础2。
10 0
计算机基础3 | 学习笔记
快速学习计算机基础3。
9 0
数据类型-数值和字符串 | 学习笔记
快速学习数据类型-数值和字符串。
5 0
作用域及作用域链 | 学习笔记
快速学习作用域及作用域链。
5 0
Linux 命令执行过程 | 学习笔记
快速学习 Linux 命令执行过程。
7 0
Linux 基本操作 | 学习笔记
快速学习 Linux 基本操作。
8 0
centOS 系统安装方法详解 | 学习笔记
快速学习 centOS 系统安装方法详解。
7 0
求数组元素的和 | 学习笔记
快速学习求数组元素的和。
6 0
系统安装前准备 | 学习笔记
快速学习系统安装前准备。
5 0
+关注
关东升
国内著名iOS/Cocos技术作家,iOS技术顾问,Cocos最有价值专家(CVP),智捷课堂首席培训专家。担任51CTO社区iOS技术顾问。 著有多部移动开发畅销书。
317
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载