Я пытаюсь получить простой пример, работающий с 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];
}
И может видеть, что мое приложение тестового сервера сокетов получает строку
"тестирование...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]?
Я чувствую, что нам нужны лучшие примеры использования этой библиотеки.