AsyncSocket库使用方法
AsyncSocket是封装了CFSocket和CFSteam的TCP/IP socket网络库。它提供了异步操作,本地cocoa类的基于delegate的完整支持
库中包含两部分:GCD和RunLoop
CGD是基于线程的 另一种是基于RunLoop的
- AsyncSocket类是支持TCP的
- AsyncUdpSocket是支持UDP的
- CGDAsyncSocket类是支持TCP的
- CGdAsyncUdpSocket是支持UDP的
CGdAsyncSocket使用方法
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![asyncSocket connectToHost:@"" onPort:123 error:nil]) {
NSLog(@"%@",error);
}
AsyncSocket使用方法
//建立socket长连接
- (void)startConnectSocket
{
self.socket = [[AsyncSocket alloc] initWithDelegate:self];
[self.socket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
if ( ![self SocketOpen:HOST port:PORT] )
{
//连接正常,可以和服务器交互
NSLog(@"正在尝试连接...");
}
}
- (NSInteger)SocketOpen:(NSString*)addr port:(NSInteger)port
{
if (![self.socket isConnected])
{
NSError *error = nil;
[self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:&error];
}
return 0;
}
#pragma mark - 断开连接 用户手动断开连接
//cutOffSocket是用户断开连接之后,不在尝试重新连接。
-(void)cutOffSocket
{
self.socket.userData = SocketOfflineByUser;
[self.socket disconnect];
}
#pragma mark - 发送消息
- (void)sendMessage:(id)message
{
//像服务器发送数据
NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:cmdData withTimeout:WRITE_TIME_OUT tag:1];
}
#pragma mark - socketDelegate
#pragma mark - socket断开之后会回调:
- (void)onSocketDidDisconnect:(AsyncSocket *)sock
{
NSLog(@"7878 对不起,连接失败 %ld",sock.userData);
if (sock.userData == SocketOfflineByServer) {
NSLog(@"原因:服务器掉线");
// 服务器掉线,重连
[self startConnectSocket];
}
else if (sock.userData == SocketOfflineByUser) {
NSLog(@"用户断开连接");
// 如果由用户断开,不进行重连
return;
}else if (sock.userData == SocketOfflineByWifiCut) {
NSLog(@"WiFi断开");
// wifi断开,不进行重连
return;
}
}
#pragma mark - socket出错回调
//socket出错会回调onSocket:willDisconnectWithError:方法,可以通过unreadData来读取来不及读取的buffer。
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
NSData * unreadData = [sock unreadData]; // ** This gets the current buffer
if(unreadData.length > 0) {
[self onSocket:sock didReadData:unreadData withTag:0]; // ** Return as much data that could be collected
} else {
NSLog(@" 即将连接出错 %ld",sock.userData);
if (sock.userData == 0) {
NSLog(@"出错原因:服务器连接出错");
NSLog(@"错误描述:%@",[err description]);
}
//wifi断开之后,会回调onSocket:willDisconnectWithError:方法,err.code == 57,这个时候设置self.socket.userData = SocketOfflineByWifiCut。
if (err.code == 57) {
self.socket.userData = SocketOfflineByWifiCut;
}
}
}
#pragma mark - 接收到新的socket回调方法
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
NSLog(@"didAcceptNewSocket");
}
#pragma mark - 连接成功回调方法
//在连接成功的回调方法里,启动定时器,每隔2秒向服务器发送固定的消息来检测长连接。(这个根据服务器的需要就可以了)
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
//这是异步返回的连接成功,
NSLog(@"已连接到服务器");
//通过定时器不断发送消息,来检测长连接
self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
[self.heartTimer fire];
}
// 心跳连接
-(void)checkLongConnectByServe{
// 向服务器发送固定可是的消息,来检测长连接
NSString *longConnect = @"connect is here";
NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:data withTimeout:1 tag:1];
}
#pragma mark - 接受消息成功之后回调
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
//服务端返回消息数据量比较大时,可能分多次返回。所以在读取消息的时候,设置MAX_BUFFER表示每次最多读取多少,当data.length < MAX_BUFFER我们认为有可能是接受完一个完整的消息,然后才解析
if( data.length < MAX_BUFFER )
{
//收到结果解析...
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@",dic);
//解析出来的消息,可以通过通知、代理、block等传出去
}
[self.socket readDataWithTimeout:READ_TIME_OUT buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
}
#pragma mark - 发送消息成功之后回调
//发送消息成功之后会调用onSocket:didWriteDataWithTag:,在这个方法里可以进行读取消息。
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
//读取消息
[self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
}