异步IO与CFReadStream
问题描述:
这是Asynchronous IO with CFWriteStream兄弟的问题。我使用CFReadStreamScheduleWithRunLoop和CFReadSteamRead做异步IO。我们如何安全地检索阻止的所有日期?我们假设一个消息的实际大小是1200(但我们不知道),而且我的读取缓冲区的大小是1024.对CFReadStreamRead的调用将检索多达1024字节的数据,但由于我们不愿意不知道消息的大小,我们应该反复调用CFReadStreamRead。问题是,因为我们不知道有多少流套接字已接收到数据时,CFReadStreamRead可能从第二个呼叫阻塞。我们如何避免这个问题?异步IO与CFReadStream
谢谢!再次CFReadStreamHasBytesAvailable()
答
请拨打流,看它是否仍然安全从中读取数据(或者,如果知道的唯一方法是尝试)。
答
我添加了一个示例代码,该做的工作对我来说。它使用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;
}
}
为了明确这一点:当我得到一个kCFStreamEventHasBytesAvailable通知为文档说,第一次调用CFReadStreamRead将是安全的。但是,我们不知道CFReadStreamRead返回的原因是否是因为缓冲区是不够大或流套接字没有更多的数据。如果在第一次通知之前收到所有1200字节的数据,我们可能无法获得其他数据的额外通知。所以我们应该再次调用CFReadStreamRead,并且不保证第二个调用不会被阻塞。这个假设是否正确? – Kay 2010-07-28 07:42:24