第2月第1天 GCDAsyncSocket dispatch_source_set_event_handler

Posted lianhuaren

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第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
                }

 

 

 

 

以上是关于第2月第1天 GCDAsyncSocket dispatch_source_set_event_handler的主要内容,如果未能解决你的问题,请参考以下文章

第2月第24天 coretext 行高

第37月第2天 tensorflow ios

第25月第2天 django项目01

第12月第2天 uiscrollview _adjustContentOffsetIfNecessary

第13月第13天 iOS 放大消失动画

第26月第2天 vim javacomplete