Update:
- It seems that fileDescriptor can be used directly in send() or sendto()
- It is better to use send() which will not block this thread
- Updated the code to end the sending if there is sending error
// Some definitions BOOL isAtOrAboveIOS5 = [yourfileHandle respondsToSelector:@selector(setWriteabilityHandler:)]; NSMutableData* pendingData = [[NSMutableData alloc] initWithCapacity:1024]; // Try to send data here // iOS 5 / OSX 10.7 or above if (isAtOrAboveIOS5 == YES) { [pendingData appendData:dataToSend]; remoteFileHandle.writeabilityHandler = ^(NSFileHandle* thisFileHandle) { int amountSent = send([thisFileHandle fileDescriptor], [pendingData bytes], [pendingData length], MSG_DONTWAIT); if (amountSent < 0) { // errno is provided by system NSLog(@"Error while sending response: %d", errno); amountSent = [pendingData length]; } [pendingData replaceBytesInRange:NSMakeRange(0, amountSent) withBytes:NULL length:0]; // Finishing if ([pendingData length] == 0) { thisFileHandle.writeabilityHandler = nil; } }; } else { [yourfileHandle writeData:dataToSend]; }
My guess of the actual problem when using writeData: after iOS 5.0 is that writeData: just tries to send as much data as possible over the socket in one shot. If there is much data than the socket can accept (this time), exception is thrown. With NSFileHandle.writeabilityHandler set, the code block is executed everytime its fileDescriptor (this time it is a socket) can accept more data. Since there is no method in NSFileHandle which tells you how many data is actually written, I used function sendto() here, but I believe there should be a better implementation exists.
No comments:
Post a Comment