溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

iOS網(wǎng)絡(luò)編程實踐--藍牙對等網(wǎng)絡(luò)通信實例講解

發(fā)布時間:2020-06-25 10:25:28 來源:網(wǎng)絡(luò) 閱讀:1578 作者:tony關(guān)東升 欄目:移動開發(fā)

基于藍牙對等網(wǎng)絡(luò)通信就是使用Game Kit中的GKSession、GKSessionDelegate、 GKPeerPickerController和GKPeerPickerControllerDelegate來實現(xiàn)。開發(fā)過程分為3個步驟:連接、發(fā) 送數(shù)據(jù)和接收數(shù)據(jù)。

下面我們通過一個實例介紹一下基于藍牙對等網(wǎng)絡(luò)通信過程。用戶點擊“連接”按鈕,建立連接過程中會出現(xiàn)連接對話框,根據(jù)具體情況也會彈出其它的對話 框。這些都是針對藍牙對等網(wǎng)絡(luò)標準對話框,而Wifi對等網(wǎng)絡(luò)沒有標準對話框可以使用,需要開發(fā)者自己實現(xiàn)。當兩個設(shè)備連接好之后,兩個玩家就可以連續(xù)輕 點“點擊”按鈕,點擊的次數(shù)會傳遞給對方,倒計時時間是30秒。

iOS網(wǎng)絡(luò)編程實踐--藍牙對等網(wǎng)絡(luò)通信實例講解

1、連接

由于對等網(wǎng)絡(luò)連接過程有點復(fù)雜,貫穿了這些協(xié)議和類,我們繪制了連接過程的流程圖。

iOS網(wǎng)絡(luò)編程實踐--藍牙對等網(wǎng)絡(luò)通信實例講解

下面我們通過代碼直接介紹連接流程,其中ViewController.h代碼如下:

 

  1. #import <UIKit/UIKit.h> 
  2.  
  3. #import <GameKit/GameKit.h> 
  4.  
  5.   
  6.  
  7. #define  GAMING 0          //游戲進行中 
  8.  
  9. #define  GAMED  1          //游戲結(jié)束 
  10.  
  11.   
  12.  
  13. @interface ViewController : UIViewController <GKSessionDelegate, GKPeerPickerControllerDelegate> 
  14.  
  15.  
  16. NSTimer *timer; 
  17.  
  18.  
  19. @property (weak, nonatomic) IBOutlet UILabel *lblTimer; 
  20.  
  21.   
  22.  
  23. @property (weak, nonatomic) IBOutlet UILabel *lblPlayer2; 
  24.  
  25. @property (weak, nonatomic) IBOutlet UILabel *lblPlayer1; 
  26.  
  27. @property (weak, nonatomic) IBOutlet UIButton *btnConnect; 
  28.  
  29. @property (weak, nonatomic) IBOutlet UIButton *btnClick; 
  30.  
  31.   
  32.  
  33. @property (nonatomic, strong) GKPeerPickerController *picker; 
  34.  
  35. @property (nonatomic, strong) GKSession *session; 
  36.  
  37.   
  38.  
  39. - (IBAction)onClick:(id)sender; 
  40.  
  41. - (IBAction)connect:(id)sender; 
  42.  
  43.   
  44.  
  45. //清除UI畫面上的數(shù)據(jù) 
  46.  
  47. -(void) clearUI; 
  48.  
  49.   
  50.  
  51. //更新計時器 
  52.  
  53. -(void) updateTimer; 
  54.  
  55.   
  56.  
  57. @end 

使用Game Kit需要引入頭文件<GameKit/GameKit.h>,之前需要把GameKit.framework框架添加 到工程中。而且定義類的時候需要實現(xiàn)協(xié)議GKSessionDelegate和GKPeerPickerControllerDelegate,并且定義 GKPeerPickerController類型的屬性picker,定義GKSession類型的屬性session。

ViewController.m中創(chuàng)建GKPeerPickerController對象的代碼如下:

 

  1. - (IBAction)connect:(id)sender { 
  2.  
  3. _picker = [[GKPeerPickerController alloc] init]; 
  4.  
  5. _picker.delegate = self; ① 
  6.  
  7. _picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;  ② 
  8.  
  9. [_picker show]; 
  10.  

用戶點擊的連接按鈕時,觸發(fā)connect:方法。在該方法中創(chuàng)建GKPeerPickerController對象。創(chuàng)建完成不要忘記設(shè)置 GKPeerPickerController委托為self,第②行代碼所示。在第③行代碼中connectionTypesMask屬性是設(shè)置對等網(wǎng) 絡(luò)連接類型,其中有兩種類型選擇:GKPeerPickerConnectionTypeNearby和 GKPeerPickerConnectionTypeOnline,GKPeerPickerConnectionTypeNearby用于藍牙通訊也 是默認的通訊方法,GKPeerPickerConnectionTypeOnline用于Wifi通訊的局域網(wǎng)通訊,這種方式麻煩,需要開發(fā)人員自己設(shè) 計UI畫面,自己使用Bonjour服務(wù)發(fā)現(xiàn)管理連接,以及自己編寫輸入輸出流實現(xiàn)通訊。如果給用戶一個選擇對話框,代碼可以如下編寫:

_picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby | GKPeerPickerConnectionTypeOnline;

iOS網(wǎng)絡(luò)編程實踐--藍牙對等網(wǎng)絡(luò)通信實例講解

其中“在線”就是GKPeerPickerConnectionTypeOnline類型,“附近”就是GKPeerPickerConnectionTypeNearby類型。

連接成功之后回調(diào)ViewController.m中的回調(diào)委托方法peerPickerController:didConnectPeer:toSession:代碼:

 

  1. - (void)peerPickerController:(GKPeerPickerController *)pk didConnectPeer:(NSString *)peerID 
  2.  
  3. toSession:(GKSession *) session 
  4.  
  5.  
  6. NSLog(@”建立連接”); 
  7.  
  8. _session = session; ① 
  9.  
  10. _session.delegate = self;  ② 
  11.  
  12. [_session setDataReceiveHandler:self withContext:nil];  ③ 
  13.  
  14. _picker.delegate = nil; 
  15.  
  16. [_picker dismiss]; ④ 
  17.  
  18. [_btnClick setEnabled:YES]; 
  19.  
  20. [_btnConnect setTitle:@"斷開連接" forState:UIControlStateNormal]; 
  21.  
  22. //開始計時 
  23.  
  24. timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self 
  25.  
  26. selector:@selector(updateTimer) 
  27.  
  28. userInfo:nil repeats:YES]; ⑤ 
  29.  

上述代碼第①行_session = session將委托方法中返回的會話參數(shù)賦值給成員變量,這樣我們就獲得了一個會話對象。這種方式中,會話 ID是應(yīng)用程序的包ID,如果想自己分配會話ID,可以實現(xiàn)下面委托方法,在方法中使用GKSession的構(gòu)造方法 initWithSessionID:displayName: sessionMode:,自己創(chuàng)建會話對象。

 

  1. - (GKSession *)peerPickerController:(GKPeerPickerController *)picker 
  2.  
  3. sessionForConnectionType:(GKPeerPickerConnectionType)type { 
  4.  
  5. GKSession *session = [[GKSession alloc] initWithSessionID: <自定義SessionID> 
  6.  
  7. displayName:<顯示的名字> sessionMode:GKSessionModePeer]; 
  8.  
  9. return session; 
  10.  

有的時候會話的狀態(tài)會發(fā)生變化,我們要根據(jù)狀態(tài)的變化做一些UI的清理和資源的釋放。監(jiān)測狀態(tài)變化在委托方法session:peer:didChangeState:中實現(xiàn),方法代碼如下:

 

  1. - (void)session:(GKSession *)session peer:(NSString *)peerID 
  2.  
  3. didChangeState:(GKPeerConnectionState)state 
  4.  
  5.  
  6. if (state == GKPeerStateConnected) 
  7.  
  8.  
  9. NSLog(@”connected”); 
  10.  
  11. [_btnConnect setTitle:@"斷開連接" forState:UIControlStateNormal]; 
  12.  
  13. [_btnClick setEnabled:YES]; 
  14.  
  15. else if (state == GKPeerStateDisconnected) 
  16.  
  17.  
  18. NSLog(@”disconnected”); 
  19.  
  20. [self clearUI]; 
  21.  
  22.  

其中GKPeerStateConnected常量是已經(jīng)連接狀態(tài),GKPeerStateDisconnected常量是斷開連接狀態(tài)。

2、發(fā)送數(shù)據(jù)

發(fā)送數(shù)據(jù)的代碼如下:

 

  1. - (IBAction)onClick:(id)sender { 
  2.  
  3. int count = [_lblPlayer1.text intValue]; 
  4.  
  5. _lblPlayer1.text = [NSString stringWithFormat:@"%i",++count]; 
  6.  
  7. NSString *sendStr = [NSString 
  8.  
  9. stringWithFormat:@"{\"code\":%i,\"count\":%i}",GAMING,count]; ① 
  10.  
  11. NSData* data = [sendStr dataUsingEncoding: NSUTF8StringEncoding]; 
  12.  
  13. if (_session) { 
  14.  
  15. [_session sendDataToAllPeers:data 
  16.  
  17. withDataMode:GKSendDataReliable  error:nil]; ② 
  18.  
  19.  

3、接收數(shù)據(jù)

為了接收數(shù)據(jù)首先需要在設(shè)置會話時候通過[_session setDataReceiveHandler:self withContext:nil]語句設(shè)置接收數(shù)據(jù)的處理程序是self。這樣當數(shù)據(jù)到達時候就會觸發(fā)下面的方法特定:

 

  1. - (void) receiveData:(NSData *)data  fromPeer:(NSString *)peer 
  2.  
  3. inSession:(GKSession *)session  context:(void *)context 
  4.  
  5.  
  6. id jsonObj = [NSJSONSerialization JSONObjectWithData:data 
  7.  
  8. options:NSJSONReadingMutableContainers error:nil]; 
  9.  
  10. NSNumber *codeObj = [jsonObj objectForKey:@"code"]; 
  11.  
  12. if ([codeObj intValue]== GAMING) { 
  13.  
  14. NSNumber * countObj= [jsonObj objectForKey:@"count"]; 
  15.  
  16. _lblPlayer2.text = [NSString stringWithFormat:@"%@",countObj]; 
  17.  
  18. else if ([codeObj intValue]== GAMED) { 
  19.  
  20. [self clearUI]; 
  21.  
  22.  

上面的代碼是接收到數(shù)據(jù)之后,進行JSON解碼,取出游戲狀態(tài)和點擊次數(shù)。

主要的程序代碼就是這些,根據(jù)具體的業(yè)務(wù)情況還可以能有所變化,讀者可以下載完整代碼在兩臺之間設(shè)備或是一個設(shè)備一個模擬器之間進行測試。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI