GCDAsyncSocket源码分析
GCDAsyncSocket.m的成员变量
@implementation GCDAsyncSocket
{
//flags 状态标志
uint32_t flags;
//config IPV4|IPV6配置
uint16_t config;
// 代理
__weak id<GCDAsyncSocketDelegate> delegate;
//代理的回调函数
dispatch_queue_t delegateQueue;
int socket4FD;
int socket6FD;
//unix套接字 //进行进程间通讯
int socketUN;
//Unix服务端
NSURL *socketUrl;
//状态Index
int stateIndex;
//本机的IPV4
NSData * connectInterface4;
//本机的IPV6
NSData * connectInterface6;
//本机Unix域地址
NSData * connectInterfaceUN;
//这个类的Soctet的操作在这queue中,串行
dispatch_queue_t socketQueue;
//souce源
dispatch_source_t accept4Source;
dispatch_source_t accept6Source;
dispatch_source_t acceptUNSource;
//链接timer,GCD定时器重连
dispatch_source_t connectTimer;
dispatch_source_t readSource;
dispatch_source_t writeSource;
dispatch_source_t readTimer;
dispatch_source_t writeTimer;
//读写数据包数组 类似queue FIFO
NSMutableArray *readQueue;
NSMutableArray *writeQueue;
//当前正在读写数据包
GCDAsyncReadPacket *currentRead;
GCDAsyncWritePacket *currentWrite;
//当前socket未获取完的数据大小
unsigned long socketFDBytesAvailable;
//全局公用的提前缓冲区
GCDAsyncSocketPreBuffer *preBuffer;
#if TARGET_OS_IPHONE
CFStreamClientContext streamContext;
//读的数据流
CFReadStreamRef readStream;
//写的数据流
CFWriteStreamRef writeStream;
#endif
//SSL上下文用来SSL验证
SSLContextRef sslContext;
//全局公用的SSL的提前缓冲区
GCDAsyncSocketPreBuffer *sslPreBuffer;
size_t sslWriteCachedLength;
//记录SSL错误信息
OSStatus sslErrCode;
OSStatus lastSSLHandshakeError;
//socket队列的标志key
void *IsOnSocketQueueOrTargetQueueKey;
id userData;
//连接备选服务器地址的延时
NSTimeInterval alternateAddressDelay;
}
GCDAsyncSocket的初始化
创建
_Socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
- (instancetype)initWithDelegate:(id<GCDAsyncSocketDelegate>)aDelegate delegateQueue:(dispatch_queue_t)dq
{
return [self initWithDelegate:aDelegate delegateQueue:dq socketQueue:NULL];
}
init方法最终将会来到,在这个方法里,同时socketQueue传值为NULL
- (instancetype)initWithDelegate:(id<GCDAsyncSocketDelegate>)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq
{
if((self = [super init]))
{
delegate = aDelegate;
delegateQueue = dq;
#if !OS_OBJECT_USE_OBJC
if (dq) dispatch_retain(dq);
#endif
socket4FD = SOCKET_NULL;
socket6FD = SOCKET_NULL;
socketUN = SOCKET_NULL;
socketUrl = nil;
stateIndex = 0;
if (sq)
{
NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
@"The given socketQueue parameter must not be a concurrent queue.");
NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
@"The given socketQueue parameter must not be a concurrent queue.");
NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
@"The given socketQueue parameter must not be a concurrent queue.");
socketQueue = sq;
#if !OS_OBJECT_USE_OBJC
dispatch_retain(sq);
#endif
}
else
{
// NSString *const GCDAsyncSocketQueueName = @"GCDAsyncSocket";
socketQueue = dispatch_queue_create([GCDAsyncSocketQueueName UTF8String], NULL);
}
// The dispatch_queue_set_specific() and dispatch_get_specific() functions take a "void *key" parameter.
// From the documentation:
//
// > Keys are only compared as pointers and are never dereferenced.
// > Thus, you can us