Как добиться выполнения didReadData в GCDAsyncSocket в текущем RunLoop?

Я пытаюсь получить простой пример работы с GCDAsyncSocket, и обнаруживаю, что мне не хватает некоторых элементов понимания, и надеюсь, вы, хорошие люди, поможете это объяснить.

Я настроил GCDAsyncSocket ниже:

dispatch_queue_t mainQueue = dispatch_get_main_queue();
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue];

NSString *host = @"192.168.169.132";
uint16_t port = 2112;

DDLogInfo(@"Connecting to \"%@\" on port %hu...", host, port);
self.viewController.label.text = @"Connecting...";

NSError *error = nil;
if (![asyncSocket connectToHost:host onPort:port withTimeout:5.0 error:&error])
{
    DDLogError(@"Error connecting: %@", error);
    self.viewController.label.text = @"Oops";
}
else
{
    DDLogVerbose(@"Connecting...");
}


- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    DDLogInfo(@"socket:%p didConnectToHost:%@ port:%hu", sock, host, port);
    self.viewController.label.text = @"Connected";

    // We're just going to send a test string to the server.

    NSString *myStr = @"testing...123...\r\n";
    NSData *myData = [myStr dataUsingEncoding:NSUTF8StringEncoding];

    [asyncSocket writeData:myData withTimeout:5.0 tag:0];
}

И вижу, что мое приложение тестового сервера сокетов получает строку

«testing ... 123 ... \ r \ n»

Но когда я тогда Если мой тестовый сервер сокетов отправит строку обратно, я наивно ожидал, что делегат didReadData выполнит

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

, но холодная суровая реальность заставила меня узнать, что до тех пор, пока я не вызову

[asyncSocket readDataWithTimeout:5.0 tag:0];

... didReadData делегат не будет вызван.

Хорошо, это нормально. Я понял.

Прочитав документацию еще немного, там ясно сказано, что

AsyncSocket - это библиотека сокетов TCP на основе RunLoop.

Итак, теперь я смотрю на этот RunLoop , который, на мой взгляд, похож на цикл сообщений в Microsoft Windows . Поскольку iOS представляет собой архитектуру, управляемую событиями / сообщениями (как и Win32), то основной поток по умолчанию, в котором я сейчас работаю, очевидно, имеет собственный цикл сообщений для обработки событий.

Меня беспокоит то, что iOS RunLoop выглядит как отдельный объект, с которым нужно работать, чтобы GCDAsyncSocket работал должным образом.

Когда он заявляет, что его набором по умолчанию режима цикла выполнения является NSDefaultRunLoopMode, который находится в основном потоке.

Еще не запутались?

Итак, в Win32 мой код обработки событий связи будет выглядеть так:

while( sCOMport.hCOMport != INVALID_HANDLE_VALUE )  // ...while the COM port is open...
{
    // Wait for an event to occur on the port.
    WaitCommEvent( sCOMport.hCOMport, &dwCommStatus, NULL );

Он, конечно, будет в отдельном потоке (еще не дошел до него с помощью GCDAsyncSocket), но это будет его собственный "RunLoop" в некотором роде.

Как мне сделать то же самое, используя GCDAsyncSocket , чтобы я не застрял в каком-то цикле опроса, заполняя очередь вызовами [asyncSocket readDataWithTimeout] ?

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

7
задан Sebastian Dwornik 3 November 2011 в 15:07
поделиться

0 ответов