之前做的通讯项目 并没有使用成熟的IM供应方,而是自己用socket做的。我用的是第三方GCDAsyncSocket,使用起来还是比较方便,记录一下遇到的一些问题 和不懂的地方。
1、创建GCDAsyncSocket实例对象。
@selector(initWithDelegate:delegateQueue:)
实例化方法
传入delegate对象,然后用于处理登陆,发送消息,接受消息的代理方法。 我单独新建的一个类用于处理消息事件,socket作为其中一个实例变量。这里delegate传的是self,queue是mainQueue。然后这个方法会调用
@selector(initWithDelegate:delegateQueue:socketQueue:)
socketQueue如果没有传入为NULL,就会自动创建一个socketQueue
socketQueue = dispatch_queue_create([GCDAsyncSocketQueueName UTF8String], NULL);,
但是如果你要自己去给一个queue的话,不能使用global_queue.否则会报错。(这里不太清楚为什么这样做,大概是保证队列不会混淆吗?)
然后给socketQueue设置标志,方便取
dispatch_queue_set_specific(socketQueue, IsOnSocketQueueOrTargetQueueKey, nonNullUnusedPointer, NULL);
2、connect
@selector(connectToHost:onPort:withTimeout:error:)
这个方法会返回Bool型来表明连接结果,同时传入error的指针(&error),
这个error用来接收的错误信息是开始连接之前,检查设置可能出现的错误(host为空,然后调用@selector(preConnectWithInterface:error:)
检查delegate,delegateQueue是否为空,IPv4,IPv6不可用)
这些都是在socketqueue里实现的。然后同时触发定时器@selector(startConnectTimeout:)
这里传入的time是之前传入的参数,如果小于0就不创建计时器,否则就创建计时器,在指定时间没有connect成功就做超时操作,取消计时器,reset所有变量,closed socket。
然后connect是先@selector(lookupHost:port:error:)
生成装有sockaddr的data的数组。失败的话,返回error不为空,然后做和超时一样的操作。成功的话先判断IPv4还是6 然后connect@selector(lookup:didSucceedWithAddress4:address6:)
(BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr
根据返回的结果
成功- (void)didConnect:(int)aConnectIndex
设置读写Sources并且调用代理方法- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
成功之后 要投递读的请求,这样才能正常接收消息。其实在没有连接上的时候也可以直接调用这个方法,这样读请求会自动进入了队列,当socket 连接上后,请求会自动出队被执行
- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag
失败- (void)didNotConnect:(int)aConnectIndex error:(NSError *)error
然后调用- (void)closeWithError:(NSError *)error
reset
在connect过程中发现任何错误 都会调用- (void)closeWithError:(NSError *)error
在这个方法里调用代理方法@selector(socketDidDisconnect:withError:)
然后成功或者失败,在代理方法里做其他的操作
3、disconnect
先判断是正在连接或则已经连接上的状态,是的话就调用- (void)closeWithError:(NSError *)error
reset所有变量,closed socket。
然后调用代理方法。
在代理方法@selector(socketDidDisconnect:withError:)
中根据error的内容可以判断连接失败的原来然后来做重连等操作。当主动disconnect的话 error应该是nil。