首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用NSStream/CFStream的TCP连接

使用NSStream/CFStream的TCP连接
EN

Stack Overflow用户
提问于 2011-12-22 04:05:26
回答 3查看 8.7K关注 0票数 1

当使用NSStream +getStreamsToHost/CFStreamCreatePairWithSocket()打开TCP流时,我正在拼命尝试找出如何检测错误。如果我这样做:

代码语言:javascript
复制
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];

status1NSStreamStatusNotOpen,这是意料之中的。error1nilerror2也是nilstatus2NSStreamStatusOpening。如果我telnet到相同的地址,我得到的连接被拒绝-没有任何东西监听端口80。如果我尝试连接到一些无意义的地址,比如yaddayadda,我得到的是nil流。

如何正确处理错误?任何地方似乎都没有处理错误条件的示例,文档也没有提到任何关于它的内容,除了流可能是空的。我被难住了。不要告诉我我必须通过run循环运行连接,才能获得适当的错误处理...?

我知道总是有可能使用好的旧的BSD套接字,但文档对此提出了警告,因为一些高级网络功能可能会失败(通过VPN的自动连接,以及类似的东西)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-22 05:36:52

您需要做的是在输入流上使用streamStatus方法轮询状态,或者在run循环中调度事件流。为了更好地提供有关错误主机名的错误信息,最好提前使用NSHostCFHost解析主机名。

票数 0
EN

Stack Overflow用户

发布于 2013-04-05 18:49:32

我遇到了同样的问题,这就是我如何解决它的。在我的例子中,我使用了SSL,但是您可以跳过这部分代码。

代码语言:javascript
复制
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;
票数 2
EN

Stack Overflow用户

发布于 2011-12-22 05:39:38

阅读苹果LINK上的流指南

您将看到您应该有一个切换流事件的方法,如下所示

代码语言:javascript
复制
 - (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");
        }
        }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8595632

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档