socket長連接 GCDAsyncSocket


基礎: http://www.2cto.com/kf/201609/546974.html

轉自: http://blog.csdn.net/u013282507/article/details/52621434

本篇文章的例子主要實現通過socket實時接收數據的一個圖文直播的功能模塊,代碼為socket工具類。利用的工具是GCDAsyncSocket;

 

工具類主要有三個功能模塊:

一、建立Socket連接,實現心跳連接,實現通過socket接收數據。

類名 Socket.h

二、數據處理模塊,處理接收到的數據,避免粘包問題。

類名DataContro.h

三、斷線重連模塊,當socket斷開時,重新啟動一個新的socket請求,定時請求服務器,當連接成功時通知當前socket重新連接。

類名ReconnectControl.h

 

Socket類的創建方法如下:

 

 

[objc]  view plain  copy
 
  1. [Socket sharedInstance].socketHost = @"wei.fm.hebrbtv.com";// host設定  
  2. [Socket sharedInstance].socketPort = 9004;// port設定  
  3. // 在連接前先進行手動斷開  
  4. [Socket sharedInstance].socket.userData = SocketOfflineByUser;  
  5. [[Socket sharedInstance] cutOffSocket];  
  6. // 確保斷開后再連,如果對一個正處於連接狀態的socket進行連接,會出現崩潰  
  7. [[Socket sharedInstance] socketConnectHost:^{  
  8. }];  
  9. [Socket sharedInstance].socket.userData = SocketOfflineByServer;  

使用時需要添加幾個通知方法

 

 

[objc]  view plain  copy
 
  1. //接收新消息通知  
  2. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(insertMessage:) name:SocketNewMessageNotification object:nil];  
  3. //socket斷開通知  
  4. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(socketConnectError) name:SocketConnectErrorNotification object:nil];  
  5. //socket連接通知  
  6. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(socketConnectSuccess) name:SocketConnectSuccessNotification object:nil];  


一、說一下Socket類里面的具體實現方法

 

連接方法

 

GCDAsyncSocket創建時需要添加一個線程 這里使用主線程,開啟成功后即開啟了一個通道,也可以理解為一個水管,后台通過這個通道不定時的發送數據過來。

 

 

 

[objc]  view plain  copy
 
  1. // socket連接  
  2. -(void)socketConnectHost:(VoidBlock)block  
  3. {  
  4.     //數據處理類清楚歷史數據  
  5.     [[DataControl shareControl] clearData];  
  6.     //回調方法  
  7.     _block = block;  
  8.     //連接socket  
  9.     self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];  
  10.     NSError *error = nil;  
  11.     [self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:3 error:&error];  
  12. }  


連接成功后進行數據讀取,開啟心跳連接;之后會在GCDAsyncSocket的代理方法中獲取后台發送的數據。

 

 

[objc]  view plain  copy
 
  1. /** 
  2.  連接成功 
  3.  */  
  4. -(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port  
  5. {  
  6.     if (_block) {  
  7.         _block();  
  8.     }  
  9.     //讀取socket中的數據  
  10.     [self readData];  
  11.     // 每隔30s像服務器發送心跳包  
  12.     _connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];// 在longConnectToSocket方法中進行長連接需要向服務器發送的訊息  
  13.     [_connectTimer fire];  
  14. }  

心跳連接:

 

 

[objc]  view plain  copy
 
  1. // 心跳連接  
  2. -(void)longConnectToSocket{  
  3.       
  4.     // 根據服務器要求發送固定格式的數據,假設為指令@".",但是一般不會是這么簡單的指令  
  5.     NSString *longConnect = @".\n";  
  6.     NSData   *dataStream  = [longConnect dataUsingEncoding:NSUTF8StringEncoding];  
  7.     [self writeData:dataStream];  
  8. }  

讀取數據方法如下,這里加入了一個數據處理類,防止粘包現象,具體原理會在下面說明

 

 

[objc]  view plain  copy
 
  1. /** 
  2.  收到服務器的數據,讀取數據成功后通過SocketDataControl處理,防止粘包 
  3.  */  
  4. -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag  
  5. {  
  6.     [self readData];  
  7.     NSLog(@"讀取成功");  
  8.     __block NSMutableArray *arr = [NSMutableArray new];  
  9.     [[DataControl shareControl] appendingData:data newData:^(NSMutableArray *models) {  
  10.         [self performSelector:@selector(sendMessage:) withObject:models];  
  11.         arr = models;  
  12.     }];  
  13. }  

 

二、收處理模塊:

  處理Socket數據粘包問題

三、斷線重連模塊

  Socket 斷線重連問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM