Using NSStreams For A TCP Connection Without NSHost
Q: Given that +getStreamsToHost:port:inputStream:outputStream:
is not supported on iOS, how can I create NSStreams for a TCP connection to a named host?
A: You can do this by exploiting the toll-free bridge between NSStream and CFStream. Use CFStreamCreatePairWithSocketToHost
to create CFStreams to the host, and then cast the resulting CFStreams to NSStreams.
Listing 1 shows an example of this. It adds a category to NSStream that implements a replacement for +getStreamsToHost:port:inputStream:outputStream:
.
A category to create TCP streams to a named host
@interface NSStream (QNetworkAdditions) |
|
+ (void)qNetworkAdditions_getStreamsToHostNamed:(NSString *)hostName |
port:(NSInteger)port |
inputStream:(out NSInputStream **)inputStreamPtr |
outputStream:(out NSOutputStream **)outputStreamPtr; |
|
@end |
|
@implementation NSStream (QNetworkAdditions) |
|
+ (void)qNetworkAdditions_getStreamsToHostNamed:(NSString *)hostName |
port:(NSInteger)port |
inputStream:(out NSInputStream **)inputStreamPtr |
outputStream:(out NSOutputStream **)outputStreamPtr |
{ |
CFReadStreamRef readStream; |
CFWriteStreamRef writeStream; |
|
assert(hostName != nil); |
assert( (port > 0) && (port < 65536) ); |
assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) ); |
|
readStream = NULL; |
writeStream = NULL; |
|
CFStreamCreatePairWithSocketToHost( |
NULL, |
(__bridge CFStringRef) hostName, |
port, |
((inputStreamPtr != NULL) ? &readStream : NULL), |
((outputStreamPtr != NULL) ? &writeStream : NULL) |
); |
|
if (inputStreamPtr != NULL) { |
*inputStreamPtr = CFBridgingRelease(readStream); |
} |
if (outputStreamPtr != NULL) { |
*outputStreamPtr = CFBridgingRelease(writeStream); |
} |
} |
|
@end |
NSStream 真的就是 CFNetwork 上的一层简单的 Objective-C 封装。但 iOS 中的 NSStream 不支持 NShost,这是一个缺陷,苹果也意识到这问题了(
http://developer.apple.com/library/ios/#qa/qa1652/_index.html),我们可以通过 NSStream 的扩展函数来实现该功能: