美文网首页
GCDAsynSocket异步线程

GCDAsynSocket异步线程

作者: wustzhy | 来源:发表于2017-10-17 10:45 被阅读14次

1. socket 实例化方法

/**
 * GCDAsyncSocket uses the standard delegate paradigm,
 * but executes all delegate callbacks on a given delegate dispatch queue.
 * This allows for maximum concurrency, while at the same time providing easy thread safety.
 * 
 * You MUST set a delegate AND delegate dispatch queue before attempting to
 * use the socket, or you will get an error.
 * 
 * The socket queue is optional.
 * If you pass NULL, GCDAsyncSocket will automatically create it's own socket queue.
 * If you choose to provide a socket queue, the socket queue must not be a concurrent queue.
 * If you choose to provide a socket queue, and the socket queue has a configured target queue,
 * then please see the discussion for the method markSocketQueueTargetQueue.
 * 
 * The delegate queue and socket queue can optionally be the same.
**/

- (id)init;
- (id)initWithSocketQueue:(dispatch_queue_t)sq;
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq;
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq;

注意:the socket queue must not be a concurrent queue.
系统提供

3个Concurrent Queues

dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t aHQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t aLQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

1个main queue

dispatch_queue_t mainQueue = dispatch_get_main_queue();

2. socket 接收消息 处理

/**********************************************delegate*********************************************************/
#pragma mark - 接收到消息
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    //转为明文消息
    NSString *secretStr  = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    //去除'\n'
    secretStr            = [secretStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    //转为消息模型(具体传输的json包裹内容,加密方式,包头设定什么的需要和后台协商,操作方式根据项目而定)
    ChatModel *messageModel = [ChatModel mj_objectWithKeyValues:secretStr];
    
    //接收到服务器的心跳
    if ([messageModel.beatID isEqualToString:TCP_beatBody]) {
        
        //未接到服务器心跳次数置为0
        _senBeatCount = 0;
        NSLog(@"------------------接收到服务器心跳-------------------");
        return;
    }
    
    //消息类型 (消息类型这里是以和服务器协商后自定义的通信协议来设定 , 包括字段名,具体的通信逻辑相关 . 当然也可以用数字来替代下述的字段名,使用switch效率更高)
    ChatMessageType messageType     = ChatMessageContentType_Unknow;
    
    //普通消息类型
    if ([messageModel.messageType isEqualToString:Message_Normal]) {
        messageType = ChatMessageType_Normal;
        
        //验证消息
    }else if ([messageModel.messageType isEqualToString:Message_Validate]){
        messageType = ChatMessageType_Validate;
        
        //系统消息
    }else if ([messageModel.messageType isEqualToString:Message_System]){
        messageType = ChatMessageType_System;
        
        //发送普通消息回执
    }else if ([messageModel.messageType isEqualToString:Message_NormalReceipt]){
        messageType = ChatMessageType_NormalReceipt;
        
        //登录成功回执
    }else if ([messageModel.messageType isEqualToString:Message_LoginReceipt]){
        messageType = ChatMessageType_LoginReceipt;
        //开始发送心跳
        [self sendBeat];
        //重新建立连接后 , 重置自动重连次数
        autoConnectCount = TCP_AutoConnectCount;
        
        //发送普通消息失败回执
    }else if ([messageModel.messageType isEqualToString:Message_InvalidReceipt]){
        messageType = ChatMessageType_InvalidReceipt;
        
        //撤回消息回执
    }else if ([messageModel.messageType isEqualToString:Message_RepealReceipt]){
        messageType = ChatMessageType_RepealReceipt;
        
        // 未知消息类型
    }else{
        messageType = ChatMessageContentType_Unknow;
    }
    
#warning  - 注意 ...
    //此处可以进行本地数据库存储,具体的就不多解释 , 通常来讲 , 每个登录用户创建一个DB ,每个DB对应3张表足够 ,一张用于存储聊天列表页 , 一张用于会话聊天记录存储,还有一张用于好友列表/群列表的本地化存储. 但是注意的一点 , 必须设置自增ID . 此外,个人建议预留出10个或者20个字段以备将来增加需求,或者使用数据库升级亦可
    
    //进行回执服务器,告知服务器已经收到该条消息(实际上是可以解决消息丢失问题 , 因为心跳频率以及网络始终是有一定延迟,当你断开的一瞬间,服务器并没有办法非常及时的获取你的连接状态,所以进行双向回执会更加安全,服务器推向客户端一条消息,客户端未进行回执的话,服务器可以将此条消息设置为离线消息,再次进行推送)
    
    //消息分发,将消息发送至每个注册的Object中 , 进行相应的布局等操作
    for (id delegate in self.delegates) {
        
        if ([delegate respondsToSelector:@selector(didReceiveMessage:type:)]) {
            [delegate didReceiveMessage:messageModel type:messageType];
        }
    }
}

详解注释
http://blog.csdn.net/qq_30513483/article/details/54668875

相关文章

  • GCDAsynSocket异步线程

    1. socket 实例化方法 注意:the socket queue must not be a concurr...

  • GCDAsynSocket之TCP简析

    GCDAsynSocket是一个开源的基于GCD的异步的socket库。它支持IPV4和IPV6地址,TLS/SS...

  • iOS多线程小结

    同步异步串行并行 同步串行:不开启线程 同步并行:不开启线程 异步串行:最多开启一个线程 异步并行:开启线程 同步...

  • 同步与异步 & 阻塞与非阻塞

    上篇说了线程,进程,cpu,内存,硬盘之间的关系,这篇说下异步和线程 异步 因为异步操作无须额外的线程负担,并且使...

  • 多线程

    多线程开发 - 异步 多线程 - 延迟 多线程 - 异步延迟 discardableResult 就是说返回值可以...

  • iOS线程 串行 并行 同步 异步

    同步异步 同步异步的主要影响:能不能开启新的线程 同步:在线程中执行,开启新线程的能力 异步:在线程中执行,开启新...

  • 本地文件队列-异步隔离设计

    常见的异步方式: 创建异步线程 每个新创建一个线程来执行异步任务,任务结束线程也终止。线程的创建成本比较大,不建议...

  • 异步执行原理简要总结

    异步http调用,线程池调用简要原理 主线程封装一个FutureTask给异步框架, 异步框架有管理类管理主线程传...

  • 如何用管程实现异步转同步

    异步的本质是利用多线程提升性能,异步一定是基于一个新开的线程,从调用线程来看是异步的,但是从新开的那个线程来看,正...

  • 显式使用线程实现异步编程

    显式使用线程实现异步编程 摘要 本章主要讨论如何显式的使用线程实现异步编程,这其中包含如何显式使用线程实现异步编程...

网友评论

      本文标题:GCDAsynSocket异步线程

      本文链接:https://www.haomeiwen.com/subject/itxruxtx.html