Функция NSFileHandle acceptConnectionInBackgroundAndNotify не работает при повторном вызове - PullRequest
1 голос
/ 13 января 2011

Я использую какао и пытаюсь создать сервер сокетов tcp для программы, которую пишу, использую NSFileHandle и метод acceptConnectionInBackgroundAndNotify. Я следовал за кодом от здесь .

Проблема, с которой я столкнулся, заключается в том, что я могу подключиться к своему клиенту один раз, но когда я пытаюсь подключиться снова, я получаю ошибку об отказе в подключении.

Перед первым подключением команда 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 Ответ

3 голосов
/ 13 января 2011

Я встречался с этой проблемой раньше.
Как только все данные прочитаны, выполните еще одно «принять соединение в фоновом режиме» для следующего раунда чтения данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...