当使用NSStream +getStreamsToHost/CFStreamCreatePairWithSocket()打开TCP流时,我正在拼命尝试找出如何检测错误。如果我这样做:
NSInputStream* input = nil;
NSOutputStream* output = nil;
[NSStream getStreamstoHost:[NSHost hostWithName:@"localhost"] port:80 inputStream:&input outputStream:&output];
NSError* error1 = [input streamError];
assert(error1 == nil);
NSStreamStatus status1 = [input streamStatus];
[input open];
NSError* error2 = [input streamError];
assert(error2 == nil);
NSStreamStatus status2 = [input streamStatus];status1为NSStreamStatusNotOpen,这是意料之中的。error1是nil。error2也是nil,status2是NSStreamStatusOpening。如果我telnet到相同的地址,我得到的连接被拒绝-没有任何东西监听端口80。如果我尝试连接到一些无意义的地址,比如yaddayadda,我得到的是nil流。
如何正确处理错误?任何地方似乎都没有处理错误条件的示例,文档也没有提到任何关于它的内容,除了流可能是空的。我被难住了。不要告诉我我必须通过run循环运行连接,才能获得适当的错误处理...?
我知道总是有可能使用好的旧的BSD套接字,但文档对此提出了警告,因为一些高级网络功能可能会失败(通过VPN的自动连接,以及类似的东西)。
发布于 2011-12-22 05:36:52
您需要做的是在输入流上使用streamStatus方法轮询状态,或者在run循环中调度事件流。为了更好地提供有关错误主机名的错误信息,最好提前使用NSHost或CFHost解析主机名。
发布于 2013-04-05 18:49:32
我遇到了同样的问题,这就是我如何解决它的。在我的例子中,我使用了SSL,但是您可以跳过这部分代码。
NSString *host = @"10.38.129.234";
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)host, 403, &readStream, &writeStream);
[readStream setProperty:NSStreamSocketSecurityLevelSSLv3 forKey:NSStreamSocketSecurityLevelKey];
[readStream setProperty:(id)kCFBooleanFalse forKey:(NSString *)kCFStreamPropertyShouldCloseNativeSocket];
[writeStream setProperty:NSStreamSocketSecurityLevelSSLv3 forKey:NSStreamSocketSecurityLevelKey];
[writeStream setProperty:(id)kCFBooleanFalse forKey:(NSString *)kCFStreamPropertyShouldCloseNativeSocket];
//Setup SSL properties
NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
@"10.38.129.234",kCFStreamSSLPeerName,
nil];
settings = [settings autorelease];
CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
//Open the OutputStream
CFWriteStreamOpen(writeStream);
UInt8 buf[] = "your message ";
[self writeToStream:writeStream :buf];
//Read the Stream
CFReadStreamOpen(readStream);
NSString *response = [self readFromStream:readStream];
if(response != nil)
{
NSLog(@"%@",response);
}
UInt8 pull[] = "another message\n";
[self writeToStream:writeStream :pull];
response = [self readFromStream:readStream];
if(response != nil)
{
NSLog(@"%@",response);
}
//Close the readstream
CFReadStreamClose(readStream);
CFRelease(readStream);
readStream = NULL;
//Close the writestream
CFWriteStreamClose(writeStream);
CFRelease(writeStream);
writeStream = NULL;发布于 2011-12-22 05:39:38
阅读苹果LINK上的流指南
您将看到您应该有一个切换流事件的方法,如下所示
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent)
{
case NSStreamEventOpenCompleted:
{
DDLogVerbose(@"Stream opened");
break;
}
case NSStreamEventHasBytesAvailable:
{
if(!rawData) {
rawData = [[NSMutableData data] retain];
}
uint8_t buf[1024];
unsigned int len = 0;
len = [(NSInputStream *)theStream read:buf maxLength:1024];
if(len) {
[rawData initWithBytes:buf length:len];
} else {
DDLogVerbose(@"no buffer!");
}
const uint8_t *bytes = [rawData bytes];
NSMutableArray *mutableBuffer = [[NSMutableArray alloc] initWithCapacity:len];
for (int i =0; i < [rawData length]; i++) {
[mutableBuffer addObject:[NSString stringWithFormat:@"%02X", bytes[i]]];
}
[self gateKeeper:mutableBuffer];
[mutableBuffer release];
break;
}
case NSStreamEventErrorOccurred:
{
if ([theStream isKindOfClass:[NSInputStream class]]) {
NSString* address = [self getAddress];
NSString* myIPAdress = [NSString stringWithFormat:@"IP Address: %@", address];
//[cClient updateRequest];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Cant Connect" message:[NSString stringWithFormat:@"Cant connect to server: %@, Make sure you are connected to the proper wireless network. Your Ip Address is %@",CCV.ipAddress,myIPAdress] delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:@"Reconnect", nil];
[alert show];
[alert release];
}
break;
}
case NSStreamEventEndEncountered:
{
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[theStream release];
break;
}
case NSStreamEventHasSpaceAvailable:
{
//DDLogVerbose(@"has space available");
break;
}
case NSStreamEventNone:
{
DDLogVerbose(@"none");
break;
}
default:
{
DDLogVerbose(@"Unknown event");
}
}
}https://stackoverflow.com/questions/8595632
复制相似问题