NSFileHandle函数acceptConnectionInBackgroundAndNotify第二次调用时不工作

时间:2011-01-13 07:26:56

标签: cocoa macos sockets

我正在使用cocoa,我正在尝试为我正在编写的程序创建一个tcp套接字服务器,我正在使用NSFileHandle和方法acceptConnectionInBackgroundAndNotify。我一直在关注here的代码。

我遇到的问题是我可以连接我的客户端一次,但当我再次尝试连接时,我收到连接拒绝错误。

在我第一次连接之前,命令sudo lsof -i -P返回以下信息:

RubyBeat  23964    pauljohnson    8u  IPv4 0x0632c274      0t0    TCP *:1234 (LISTEN)

第一次与客户连接后,我得到了这个:

RubyBeat  23964    pauljohnson    5u  IPv4 0x06a30334      0t0    TCP localhost:1234->localhost:51579 (CLOSED)

我的应用程序似乎没有重新打开套接字以在第一次进入后侦听连接,并在我第二次尝试连接时获得错误号22。

我在可可中使用垃圾收集,并想知道这是否会导致套接字出现问题?

我的代码是:

    [self createSocket];
}

-(void)createSocket 
{
    // create socket and wait for events to come in
    NSSocketPort* serverSock = [[NSSocketPort alloc] initWithTCPPort: 1234];
    socketHandle = [[NSFileHandle alloc] initWithFileDescriptor: [serverSock socket]
                                                 closeOnDealloc: NO];

    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(newConnection:) 
                                                 name: NSFileHandleConnectionAcceptedNotification
                                               object: socketHandle];

    [socketHandle acceptConnectionInBackgroundAndNotify];
}

- (void)newConnection:(NSNotification*)notification
{
    NSLog(@"connection accepted");

    NSDictionary* userInfo = [notification userInfo];
    NSFileHandle* remoteFileHandle = [userInfo objectForKey:
                                      NSFileHandleNotificationFileHandleItem];

    if([[userInfo allKeys] containsObject:@"NSFileHandleError"]){
        NSNumber* errorNo = [userInfo objectForKey:@"NSFileHandleError"];
        if( errorNo ) {
            NSLog(@"NSFileHandle Error: %@", errorNo);
            return;
        }
    }

    [socketHandle acceptConnectionInBackgroundAndNotify];


    [[NSNotificationCenter defaultCenter] addObserver:self 
       selector: @selector(processSocketData:)
           name: NSFileHandleReadCompletionNotification
         object: remoteFileHandle];

    // Send a message to the client, acknowledging that the connection was accepted
    [remoteFileHandle writeData: [@"OK" dataUsingEncoding: NSASCIIStringEncoding]];

    [remoteFileHandle readInBackgroundAndNotify];
}

/*
 Handle client data
 */
- (void)processSocketData:(NSNotification *)note
{
    NSData *data = [[note userInfo]
                    objectForKey:NSFileHandleNotificationDataItem];

    NSNumber* errorNo = [[note userInfo] objectForKey:@"NSFileHandleError"];
    if( errorNo ) {
        NSLog(@"NSFileHandle Error: %@", errorNo);
        return;
    }

    // Do something here with your data

    // search string for \n\n that terminates event
    NSString* stringData = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
    NSLog(@"data received: %@", stringData);

    NSDictionary* lastEvent = nil;

    NSRange range =  [stringData rangeOfString: @"\n\n"];

    if (range.location != NSNotFound) {
        NSArray* subStrings = [stringData componentsSeparatedByString:@"\n\n"];

        NSMutableArray* events = [[NSMutableArray alloc] init]; 

        [eventBuffer appendString: [subStrings objectAtIndex: 0]];

        // handle first event - could be in parts
        NSDictionary * json = (NSDictionary*)[eventBuffer JSONValue];

        [events addObject:json];

        for(int i = 1; i < [subStrings count]-1; i++){
            NSString* subString = [subStrings indexOfObject:i];

            NSDictionary * eventJson = (NSDictionary*)[subString JSONValue];

            [events addObject:eventJson];
        }

        // we have at least one event to draw here

        for(NSDictionary* event in events){
            NSLog(@"event: %@", [event objectForKey:@"type"]);
        }

        lastEvent = [events lastObject];

        // clear eventBuffer
        [eventBuffer setString:@""];

        // add end of data to eventBuffer?
    }else {
        [eventBuffer appendString:stringData];

    }

    // check event if it is a program exit event then stop receiving data

    if([[lastEvent objectForKey: @"type"] compare: @"exit"] != NSOrderedSame){
        // Tell file handle to continue waiting for data
        [[note object] readInBackgroundAndNotify];
    }else {


        NSLog(@"exit received stopping receiving data");
    }

}

1 个答案:

答案 0 :(得分:3)

我之前遇到过这个问题 读取所有数据后,执行另一个“接受后台连接”以获取另一轮读取数据。