您的位置:首页 > 其它

利用GCDAsyncSocket实战经验

2016-09-22 13:32 190 查看
本篇文章的例子主要实现通过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
b325
:) withObject:models];
arr = models;
}];
}


二、收处理模块:

  处理Socket数据粘包问题

三、断线重连模块

  Socket
断线重连问题


代码文件:

 代码文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: