基礎: 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類的創建方法如下:
- [Socket sharedInstance].socketHost = @"wei.fm.hebrbtv.com";// host設定
- [Socket sharedInstance].socketPort = 9004;// port設定
- // 在連接前先進行手動斷開
- [Socket sharedInstance].socket.userData = SocketOfflineByUser;
- [[Socket sharedInstance] cutOffSocket];
- // 確保斷開后再連,如果對一個正處於連接狀態的socket進行連接,會出現崩潰
- [[Socket sharedInstance] socketConnectHost:^{
- }];
- [Socket sharedInstance].socket.userData = SocketOfflineByServer;
使用時需要添加幾個通知方法
- //接收新消息通知
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(insertMessage:) name:SocketNewMessageNotification object:nil];
- //socket斷開通知
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(socketConnectError) name:SocketConnectErrorNotification object:nil];
- //socket連接通知
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(socketConnectSuccess) name:SocketConnectSuccessNotification object:nil];
一、說一下Socket類里面的具體實現方法
連接方法
GCDAsyncSocket創建時需要添加一個線程 這里使用主線程,開啟成功后即開啟了一個通道,也可以理解為一個水管,后台通過這個通道不定時的發送數據過來。
- // socket連接
- -(void)socketConnectHost:(VoidBlock)block
- {
- //數據處理類清楚歷史數據
- [[DataControl shareControl] clearData];
- //回調方法
- _block = block;
- //連接socket
- self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
- NSError *error = nil;
- [self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:3 error:&error];
- }
連接成功后進行數據讀取,開啟心跳連接;之后會在GCDAsyncSocket的代理方法中獲取后台發送的數據。
- /**
- 連接成功
- */
- -(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
- {
- if (_block) {
- _block();
- }
- //讀取socket中的數據
- [self readData];
- // 每隔30s像服務器發送心跳包
- _connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];// 在longConnectToSocket方法中進行長連接需要向服務器發送的訊息
- [_connectTimer fire];
- }
心跳連接:
- // 心跳連接
- -(void)longConnectToSocket{
- // 根據服務器要求發送固定格式的數據,假設為指令@".",但是一般不會是這么簡單的指令
- NSString *longConnect = @".\n";
- NSData *dataStream = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
- [self writeData:dataStream];
- }
讀取數據方法如下,這里加入了一個數據處理類,防止粘包現象,具體原理會在下面說明
- /**
- 收到服務器的數據,讀取數據成功后通過SocketDataControl處理,防止粘包
- */
- -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
- {
- [self readData];
- NSLog(@"讀取成功");
- __block NSMutableArray *arr = [NSMutableArray new];
- [[DataControl shareControl] appendingData:data newData:^(NSMutableArray *models) {
- [self performSelector:@selector(sendMessage:) withObject:models];
- arr = models;
- }];
- }
二、收處理模塊:
三、斷線重連模塊
