第2月第1天 GCDAsyncSocket dispatch_source_set_event_handler

一、GCDAsyncSocket的核心就是dispatch_source_set_event_handler

1.accpet回调

            accept4Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket4FD, 0, socketQueue);

            int socketFD = socket4FD;
            dispatch_source_t acceptSource = accept4Source;

            dispatch_source_set_event_handler(accept4Source, ^{ @autoreleasepool {

                LogVerbose(@"event4Block");

                unsigned long i = 0;
                unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);

                LogVerbose(@"numPendingConnections: %lu", numPendingConnections);

                while ([self doAccept:socketFD] && (++i < numPendingConnections));
            }});

2.read,write回调

    readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socketFD, 0, socketQueue);
    writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, socketFD, 0, socketQueue);

    // Setup event handlers

    dispatch_source_set_event_handler(readSource, ^{ @autoreleasepool {

        LogVerbose(@"readEventBlock");

        socketFDBytesAvailable = dispatch_source_get_data(readSource);
        LogVerbose(@"socketFDBytesAvailable: %lu", socketFDBytesAvailable);

        if (socketFDBytesAvailable > 0)
            [self doReadData];
        else
            [self doReadEOF];
    }});

    dispatch_source_set_event_handler(writeSource, ^{ @autoreleasepool {

        LogVerbose(@"writeEventBlock");

        flags |= kSocketCanAcceptBytes;
        [self doWriteData];
    }});

二,缓存区

1.创建

GCDAsyncReadPacket没有传入buffer,则readpacket没有缓冲区,socket可读时会放入preBuffer

- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
{
    [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag];
}

- (void)readDataToData:(NSData *)data
           withTimeout:(NSTimeInterval)timeout
                buffer:(NSMutableData *)buffer
          bufferOffset:(NSUInteger)offset
                   tag:(long)tag
{
    [self readDataToData:data withTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag];
}

- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag
{
    [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:length tag:tag];
}

- (void)readDataToData:(NSData *)data
           withTimeout:(NSTimeInterval)timeout
                buffer:(NSMutableData *)buffer
          bufferOffset:(NSUInteger)offset
             maxLength:(NSUInteger)maxLength
                   tag:(long)tag
{
    if ([data length] == 0) {
        LogWarn(@"Cannot read: [data length] == 0");
        return;
    }
    if (offset > [buffer length]) {
        LogWarn(@"Cannot read: offset > [buffer length]");
        return;
    }
    if (maxLength > 0 && maxLength < [data length]) {
        LogWarn(@"Cannot read: maxLength > 0 && maxLength < [data length]");
        return;
    }

    GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer
                                                              startOffset:offset
                                                                maxLength:maxLength
                                                                  timeout:timeout
                                                               readLength:0
                                                               terminator:data
                                                                      tag:tag];

    dispatch_async(socketQueue, ^{ @autoreleasepool {

        LogTrace();

        if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
        {
            [readQueue addObject:packet];
            [self maybeDequeueRead];
        }
    }});

    // Do not rely on the block being run in order to release the packet,
    // as the queue might get released without the block completing.
}

三、面向对象封装

1.socket可读的时候先用preBuffer接收,拷贝到currentRead->buffer中,为生产者-消费者模式.

    GCDAsyncReadPacket *currentRead;
    GCDAsyncWritePacket *currentWrite;

    GCDAsyncSocketPreBuffer *preBuffer;
        uint8_t *buffer;

        if (readIntoPreBuffer)
        {
            [preBuffer ensureCapacityForWrite:bytesToRead];

            buffer = [preBuffer writeBuffer];
        }

。。。

            int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD;

            ssize_t result = read(socketFD, buffer, (size_t)bytesToRead);
            LogVerbose(@"read from socket = %i", (int)result);

。。。

                if (readIntoPreBuffer)
                {
                    // We just read a big chunk of data into the preBuffer

                    [preBuffer didWrite:bytesRead];
                    LogVerbose(@"read data into preBuffer - preBuffer.length = %zu", [preBuffer availableBytes]);

                    // Search for the terminating sequence

                    bytesToRead = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done];
                    LogVerbose(@"copying %lu bytes from preBuffer", (unsigned long)bytesToRead);

                    // Ensure there‘s room on the read packet‘s buffer

                    [currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead];

                    // Copy bytes from prebuffer into read buffer

                    uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset
                                                                                     + currentRead->bytesDone;

                    memcpy(readBuf, [preBuffer readBuffer], bytesToRead);

                    // Remove the copied bytes from the prebuffer
                    [preBuffer didRead:bytesToRead];
                    LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]);

                    // Update totals
                    currentRead->bytesDone += bytesToRead;
                    totalBytesReadForCurrentRead += bytesToRead;

                    // Our ‘done‘ variable was updated via the readLengthForTermWithPreBuffer:found: method above
                }
时间: 2024-10-19 06:42:52

第2月第1天 GCDAsyncSocket dispatch_source_set_event_handler的相关文章

XMPP适配IPV6 (GCDAsyncSocket适配IPV6)

苹果公司要求在6月1号之后上架Appstore的应用必须通过ipv6兼容测试. 最近到了八月份,开始发现新上架的app没有通过,查看了下原因,说没有适配IPV6. 首先在本地搭建一个IPV6的测试环境,使用mac搭建详情请看 http://blog.csdn.net/yuwuchaio/article/details/51459705 如果项目用使用了XMPP 你会发现在IPV6环境下根本登陆不上了,究极原因,是因为XMPP使用了第三方的socket库:CocoaAsyncSocket,里面包含

2017年5月26日 20:56:11

自己写api文档. 不要自负的认为自己不需要文档,你不需要别人需要啊.看了一个月的别人的接口文档,今天学着自己动手写api文档. api文档最重要的包括: 接口名 言简意赅 GetActivityModel 接口作用 再次翻译一下上面接口名字是什么意思 接口参数:input 元素 类型 是否必须 名称 描述 ID int 必须 userID 用户唯一主键 primary key prefession name string 必须 prefessionName 职业名称 isDimission 

老男孩教育每日一题-2017年5月11-基础知识点: linux系统中监听端口概念是什么?

1.题目 老男孩教育每日一题-2017年5月11-基础知识点:linux系统中监听端口概念是什么? 2.参考答案 监听端口的概念涉及到网络概念与TCP状态集转化概念,可能比较复杂不便理解,可以按照下图简单进行理解? 将整个服务器操作系统比喻作为一个别墅 服务器上的每一个网卡比作是别墅中每间房间 服务器网卡上配置的IP地址比喻作为房间中每个人 而房间里面人的耳朵就好比是监听的端口 当默认采用监听0.0.0.0地址时,表示房间中的每个人都竖起耳朵等待别墅外面的人呼唤当别墅外面的用户向房间1的人呼喊时

用PHP打印出前一天的时间,打印格式是2007年5月10日22:21:21

答案1: <?php echo date('Y'.'年'.'m'.'月'.'d'.'日'.' H:i:s',strtotime('-1 day')); 输出结果: Warning: strtotime(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() f

统计机构:2016年9月Win10全球市场份额轻微下滑

10月2日消息,根据操作系统市场数据统计机构Net Applications报告,在2016年9月份Win10全球市场份额实际上出现了轻微下滑趋势,这有点出乎大家的意料. 此前报道,在8月份微软已经停止向Win7.Win8.1用户推送Win10免费升级服务,当时Windows10市场份额已经达到22.99%,根据Net Applications的2016年9月份数据显示,Win10份额轻微下滑到22.53%. 在这份报告中,Win7系统依然是大丰娱乐桌面操作系统老大,份额为48.27%,相比8月

2016年9月全球桌面系统份额:Win7为39.38%,Win10达

10月1日消息,数据调研机构StatCounter目前给出了2016年9月份全球茗彩娱乐桌面系统市场份额统计排名,数据显示,Win10的增长势头依然良好,在市场份额上和目前排名第一的Win7还有15%左右的差距. 虽然微软在7月29日停止了Windows10免费更新服务,虽然此前微软在2018财年创造10亿Win10用户的目标看起来已经无法实现,但Win10推出后的整体势头依然有目共睹.根据StatCounter的数据,截止2016年9月,Win10已经占据24.46%的市场份额,而Win7为3

月订单超6000,汉腾X7何以引领国产SUV风潮?

随着生活消费水平的不断提升,越来越多的家庭用户在出行购车方面,越发开始着重选择实用与功能性车型为主,而SUV作为家居型首选车行,一时之间便理所当然低成为大多家庭用户的关注目标.在这种情况下,面对市场需求而相继推出的SUV车型数不胜数,除了博越.RX5.长安CX70.风光580等品牌车型外,刚刚于9月初上市的汉腾X7更是以极优的性价比和独特的设计外观成为市场的新宠,尤其是其上市第一个月订单就超过6000多台的好成绩,更是刷新了国产SUV的市场新高度. 那么,这款SUV究竟有哪些创新之处呢? 1.外

读&lt;&lt;人月神话&gt;&gt;

这本书在软件领域知名度很高,每次看到年度推荐的文章里面都有这本书且强烈推荐.出版30年了,可谓经典. 但我在读的过程中并没有那么深的体会.书中很多章节都是基于大型项目或者大型系统的经验总结,至今为止我还没有参与大于30人的项目.只能说自己的境界还不够. 第一章,焦油坑 再也找不到一个词比焦油坑更能形容,软件开发的过程了.我们都在挣扎.计划,计划,不断计划,但还是拖延,拖延,拖延.... 职业的乐趣: 创造性,贡献助人为乐,过程的魅力或者解决问题的成就感或写代码的快感,持续学习新事物,驾驭感. 职

WINDOWS 10 企业版LTSB 2015年11月补丁更新情况

WINDOWS 10 企业版LTSB 2015年11月补丁与其他WINDOWS 10版本自动更新KB3105213,按微软对LTSB的规划,LTSB不会轻易增加新功能,所以不会收到其他版本推送的1511更新包,安装这个KB3105213不会改变LTSB内部版本号,LTSB目前内部版本号还是10240, 不会更新到10586版本. LTSB的内部版本按以前的官方说明,一年只会升级一次