我如何知道我的客户端iOS应用程序是否已连接到服务器?

时间:2011-06-15 11:16:21

标签: cocoa-touch networking client-server cfnetwork

我按下按钮连接到服务器(TCP),但我不知道它是否连接.. 这是代码的一部分:

[self connectToServerUsingCFStream:msg portNo:50000];

    if(readStream && writeStream)
    {
        NSString *newText = [[NSString alloc] initWithFormat:@"Connected!! :)"]; 
        statusText.text = newText;
        [newText release];
        pingButton.hidden = NO;
    }
    else
    {
        NSString *newText = [[NSString alloc] initWithFormat:@"Connection unsuccessful :("]; 
        statusText.text = newText;
        [newText release];
    }

即使服务器处于离线状态,我总是得到“Connected !! :)”:s

2 个答案:

答案 0 :(得分:7)

遵循连接方法的人的解决方案:

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, 
                                   (CFStringRef) urlStr, 
                                   portNo, 
                                   &readStream, 
                                   &writeStream);

if (readStream && writeStream) 
{
    CFReadStreamSetProperty(readStream, 
                            kCFStreamPropertyShouldCloseNativeSocket, 
                            kCFBooleanTrue);
    CFWriteStreamSetProperty(writeStream, 
                             kCFStreamPropertyShouldCloseNativeSocket, 
                             kCFBooleanTrue);

    iStream = (NSInputStream *)readStream;
    [iStream retain];
    [iStream setDelegate:self];
    [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
                       forMode:NSDefaultRunLoopMode];
    [iStream open];

    oStream = (NSOutputStream *)writeStream;
    [oStream retain];
    [oStream setDelegate:self];
    [oStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
                       forMode:NSDefaultRunLoopMode];
    [oStream open];         
} 

正在使用

-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent

像这样:

-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
NSString *io;
if (theStream == iStream) io = @">>";
else io = @"<<";

NSString *event;
switch (streamEvent)
{
    case NSStreamEventNone:
        event = @"NSStreamEventNone";
        statusText.text =  @"Can not connect to the host!";
        break;

    case NSStreamEventOpenCompleted:
        event = @"NSStreamEventOpenCompleted";
        pingButton.hidden = NO;
        statusText.text = @"Connected";
        break;

    case NSStreamEventHasBytesAvailable:
        event = @"NSStreamEventHasBytesAvailable";
        if (theStream == iStream)
        {
            //read data
            uint8_t buffer[1024];
            int len;
            while ([iStream hasBytesAvailable])
            {
                len = [iStream read:buffer maxLength:sizeof(buffer)];
                if (len > 0)
                {
                    NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
                    NSData *theData = [[NSData alloc] initWithBytes:buffer length:len];
                    if (nil != output)
                    {
                        //do something with data
                    }
                }
            }
        }
        break;

    case NSStreamEventHasSpaceAvailable:
        event = @"NSStreamEventHasSpaceAvailable";
        if (theStream == oStream)
        {
            //send data
            uint8_t buffer[11] = "I send this";             
            int len;

            len = [oStream write:buffer maxLength:sizeof(buffer)];
            if (len > 0)
            {
                NSLog(@"Command send");
                [oStream close];
            }
        }

        break;

    case NSStreamEventErrorOccurred:
        event = @"NSStreamEventErrorOccurred";
        statusText.text = @"Can not connect to the host!";
        pingButton.hidden = YES;
        break;

    case NSStreamEventEndEncountered:
        event = @"NSStreamEventEndEncountered";
        statusText.text = @"Connection closed by the server.";
        pingButton.hidden = YES;
        [theStream close];
        [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [theStream release];
        theStream = nil;
        break;

    default:
        event = @"** Unknown";
}

NSLog(@"%@ : %@", io, event);
}

(据我所知!)这些学分来自this post deksa (虽然我不知道谁是创作者,因为我已经在网络,包括这里o SO)。这个代码稍微修改了一下(pingButton,statusText),如果你想让原始代码转到前面提到的链接。

Apple Developer Site也有一些信息。

就像我说的那样,我在网上看到过这样的东西,但现在我明白连接后发生的一切都是“自动的”;例如,如果服务器处于保持状态read(),则会自动调用case NSStreamEventHasSpaceAvailable:,并且其中的所有代码都将运行。

现在我认为这个问题得到了回答。

答案 1 :(得分:1)

虽然您没有提供足够的信息,但我建议对HTTP使用ASIHTTPRequest,对TCP和UDP使用AsyncSocket。如果建立了连接,将触发回调方法,

我不得不说,我对CFNetwork的体验非常有限,但对我而言,好像你只是在测试,如果流对象存在(if(readStream && writeStream))。 快速查看CFNetwork Programming Guide: Working with Read Streams告诉我,你必须用CFReadStreamOpen()打开它,这个函数将返回一个布尔值,如果它确实打开了流。

if (!CFReadStreamOpen(myReadStream)) {
    CFStreamError myErr = CFReadStreamGetError(myReadStream);
    // An error has occurred.
        if (myErr.domain == kCFStreamErrorDomainPOSIX) {
        // Interpret myErr.error as a UNIX errno.
        } else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) {
        // Interpret myErr.error as a MacOS error code.
            OSStatus macError = (OSStatus)myErr.error;
        // Check other error domains.
    }
}

<强>顺便说一句:
而不是

NSString *newText = [[NSString alloc] initWithFormat:@"Connected!! :)"]; 
statusText.text = newText;
[newText release];

你可以写statusText.text = @"Connected!! :)";