【问题标题】:Asynchronous IO with CFReadStream带 CFReadStream 的异步 IO
【发布时间】:2010-07-27 13:16:47
【问题描述】:

这是Asynchronous IO with CFWriteStream 的同级问题。我正在使用 CFReadStreamScheduleWithRunLoop 和 CFReadSteamRead 来做异步 IO。我们如何通过阻塞安全地检索所有日期?

假设消息的实际大小为 1200(但我们不知道),而我的读取缓冲区大小为 1024。调用 CFReadStreamRead 将检索最多 1024 字节的数据,但由于我们不知道不知道消息的大小,我们应该反复调用 CFReadStreamRead。问题是,由于我们不知道流套接字接收了多少数据,CFReadStreamRead 可能会阻止第二次调用。我们怎样才能避免这个问题?

谢谢!

【问题讨论】:

  • 明确一点:当我收到文档所述的 kCFStreamEventHasBytesAvailable 通知时,第一次调用 CFReadStreamRead 是安全的。但我们不知道 CFReadStreamRead 返回的原因是缓冲区不够大还是流套接字没有更多数据。如果在第一次通知之前已收到所有 1200 字节的数据,我们可能不会收到剩余数据的额外通知。所以我们应该对 CFReadStreamRead 进行第二次调用,并且不能保证第二次调用不会阻塞。假设正确吗?

标签: iphone cocoa networking network-programming


【解决方案1】:

在您的信息流上再次致电CFReadStreamHasBytesAvailable(),看看是否仍然可以安全地从中读取信息(或者知道的唯一方法是尝试)。

【讨论】:

    【解决方案2】:

    我添加了一个示例代码,它为我完成了这项工作。它使用 CFReadStreamHasBytesAvailable()。检查流的状态很重要,否则您可能会陷入无限循环。我的示例还包括超时处理。

    NSMutableData* bodyData = [NSMutableData dataWithCapacity:kHTTPReadStreamBufferSize];
        NSDate* startTimeStamp = [NSDate date];
    
        while (TRUE) {
            if (CFReadStreamHasBytesAvailable(httpReadStream)) {
                startTimeStamp = [NSDate date];
                UInt8* streambuffer = malloc(kHTTPReadStreamBufferSize);
                int readBytes = CFReadStreamRead (httpReadStream,streambuffer,kHTTPReadStreamBufferSize);
                NSLog(@"Read: %d",readBytes);
                [bodyData appendBytes:streambuffer length:readBytes];
                free(streambuffer);
            }
    
            if (CFReadStreamGetStatus(httpReadStream) == kCFStreamStatusError) {
                *error = (NSError*)CFReadStreamCopyError (httpReadStream);
                if ([*error code] == 61) {
                    NSLog(@"Error occured: %d",[*error code]);
                    // connection refused
                    [PlusError errorForDomainWithCode:kPlusHostUnreachable errorDescription:NSLocalizedString(@"kPlusHostUnreachable",@"")
                                      underlyingError:nil url:nil toError:error];
    
                }
                *responseHeader = nil;
                *bodyContent = nil;
                break;          
            }
    
            if (CFReadStreamGetStatus(httpReadStream) == kCFStreamStatusAtEnd) {
                NSLog(@"Stream reached end!");
                *responseHeader = (CFHTTPMessageRef)CFReadStreamCopyProperty(httpReadStream, kCFStreamPropertyHTTPResponseHeader);      
                *error = nil;
                break;
            }
    
            // timeout management
            NSTimeInterval timeInterval = [startTimeStamp timeIntervalSinceNow]*-1;
            if (timeInterval >= kHTTPReadTimeOutTimeInSeconds) {
                [PlusError errorForDomainWithCode:kPlusResourceLoadingError errorDescription:NSLocalizedString(@"kPlusResourceLoadingError",@"") 
                                  underlyingError:nil url:nil toError:error];
    
                break;
            }   
        }
    

    【讨论】:

      猜你喜欢
      • 2011-03-21
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多