GCDAsyncSocket使用
1:通过pod导入 pod 'CocoaAsyncSocket'
2:导入头文件 #import <GCDAsyncSocket.h>
3:.h文件 :声明变量,遵循代理,单利
#import "SynthesizeSingleton.h"//单利
#import GCDAsyncSocket.h
@interface BYSocketManager : NSObject<GCDAsyncSocketDelegate>
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(BYSocketManager);
@property (nonatomic, strong) GCDAsyncSocket *socket;
@property (nonatomic, retain) NSTimer *connectTimer; // 计时器
/**
重新连接socket
*/
- (void)socketReconnect;
/**
socket连接
*/
-(void)socketConnectHost;
/**
socket发送消息
*/
-(void)socketSendMessage:(NSString*)messageText;
/**
断开socket连接
*/
-(void)socketCutOff;
/**
是否是主动断开连接
*/
@property(nonatomic,assign)BOOL isActiveDisconnection;
@end
.m文件 实现方法
#import "BYSocketManager.h"
@implementation BYSocketManager
SYNTHESIZE_SINGLETON_FOR_CLASS(BYSocketManager);
/**
重新连接socket
*/
- (void)socketReconnect{
if(self.socket==nil){// 创建socket
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
}
if (!self.socket.isConnected){// 连接socket
NSError*error;
[self.socket connectToHost:IP或域名 onPort:端口 withTimeout:-1error:&error];
if(error) {
BYLog(@"重连socket错误:::%@",error);
}
}
}
/**
socket连接
*/
-(void)socketConnectHost{
if(self.socket==nil){// 创建socket
// 并发队列,这个队列将影响delegate回调,但里面是同步函数!保证数据不混乱,一条一条来
// 这里最好是写自己并发队列
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
}
if (!self.socket.isConnected){ // 连接socket
NSError*error;
[self.socket connectToHost:IP或域名 onPort:端口 withTimeout:-1error:&error];
if(error) {
BYLog(@"连接socket错误:::%@",error);
}
}
}
/**
socket发送消息
*/
-(void)socketSendMessage:(NSString*)messageText{
if(BYNullString(messageText)) {//检验是否为空
return;
}
BYLog(@"发送的消息:::%@",messageText);
NSData *data = [messageText dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:data withTimeout:-1 tag:10086];
}
/**
断开socket连接
*/
-(void)socketCutOff{
if (self.connectTimer) {
[self.connectTimerinvalidate];//定时器销毁
}
self.isActiveDisconnection = YES;
[self.socket disconnect];
}
#pragma mark socketDelegate
//已经连接到服务器
- (void)socket:(GCDAsyncSocket*)sockdidConnectToHost:(nonnullNSString*)hostport:(uint16_t)port{
self.isActiveDisconnection = NO;//已连接说明连接不再断开
BYLog(@"连接成功 : %@---%d",host,port);
//连接成功或者收到消息,必须开始read,否则将无法收到消息==继续监听服务器的消息
//不read的话,缓存区将会被关闭。 -1:表示无限时长 ,永久不失效。tag是标记
[self.socket readDataWithTimeout:-1 tag:10086];
//建立连接后立即发送登陆的json数据
NSString * sockDict1 = [NSString stringWithFormat:@"{\"%@\":\"%@\",\"%@\":\"%@\"}",@"msg_type",@"3",@"app_type",@"ios"];
[self.socket writeData:[sockDict1 dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:34];//向连接的socket发送登录json数据消息
//设置定时检测
_connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(connectTimerRun) userInfo:nil repeats:YES];
}
// 连接断开
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
BYLog(@"断开 socket连接 原因:%@",err);
//BRYLog(@"断开连接::sorry the connect is failure %ld",sock.userData);
if (self.isActiveDisconnection == YES) {// 如果由用户断开,不进行重连
return;
}else{
[self socketReconnect];// 服务器掉线,重连
}
}
//已经接收服务器返回来的数据
- (void)socket:(GCDAsyncSocket*)sockdidReadData:(NSData*)datawithTag:(long)tag{
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
BYLog(@"接收到tag = %ld : %ld 长度的数据,收到服务器消息==%@",tag,data.length,dict);
if([dict[@"msg_type"]intValue] ==1) {
}else if ([dict[@"msg_type"] intValue] == 9) {//BRYLog(@"收到了服务器的消息要返回给服务器数据");==心跳连接
[self socketSendMessage:[NSString stringWithFormat:@"{\"%@\":\"%@\",\"%@\":\"%@\"}\n",@"msg_type",@"9",@"client_ok",@"1"]];
}
//连接成功或者收到消息,必须开始read,否则将无法收到消息==继续监听服务器的消息
//不read的话,缓存区将会被关闭。 -1:表示无限时长 ,永久不失效。tag是标记 继续准备接受消息
[self.socket readDataWithTimeout:-1 tag:10086];
}
//消息发送成功 代理函数 向服务器 发送消息
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
BYLog(@"%ld 发送数据成功",tag);
}
//定时向服务器发送消息==心跳连接
- (void)connectTimerRun{
[self socketSendMessage:[NSString stringWithFormat:@"{\"%@\":\"%@\"}\n",@"msg_type",@"9"]];
}
@end
单利文件:SynthesizeSingleton(直接网上搜索也行,拖进你的项目中)
引用方法:在你创建的单利文件中:
.h文件:SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(你创建的类名);
.m文件:SYNTHESIZE_SINGLETON_FOR_CLASS(你创建的类名);
//
// SynthesizeSingleton.h
// ISO-Tools
//
// Created by yinglong zhang on 12-12-2.
//
//
#if __has_feature(objc_arc)
#define SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(classname) \
\
+ (classname *)shared##classname;
#define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \
\
static classname *shared##classname = nil; \
\
+ (classname *)shared##classname \
{ \
static dispatch_once_t pred; \
dispatch_once(&pred, ^{ shared##classname = [[classname alloc] init]; }); \
return shared##classname; \
}
#else
#define SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(classname) \
\
+ (classname *)shared##classname;
#define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \
\
static classname *shared##classname = nil; \
\
+ (classname *)shared##classname \
{ \
static dispatch_once_t pred; \
dispatch_once(&pred, ^{ shared##classname = [[classname alloc] init]; }); \
return shared##classname; \
} \
\
- (id)copyWithZone:(NSZone *)zone \
{ \
return self; \
} \
\
- (id)retain \
{ \
return self; \
} \
\
- (NSUInteger)retainCount \
{ \
return NSUIntegerMax; \
} \
\
- (oneway void)release \
{ \
} \
\
- (id)autorelease \
{ \
return self; \
}
#endif
网友评论