Длинный опрос в objective-C
У меня есть приложение, которое использует API для получения обновлений в реальном времени на веб-сайте. Они используют так называемый метод долгого опроса:
Длительный опрос - это вариация традиционная техника опроса и позволяет эмуляцию информации нажмите от сервера к клиенту. С длительный опрос, клиент запрашивает информация с сервера в аналогично обычным опросам. Однако, если на сервере нет информация, доступная для клиента, вместо отправки пустого ответа, сервер хранит запрос и ждет для получения некоторой информации. Как только информация станет доступной (или после подходящего тайм-аута), полный ответ отправляется клиент. Обычно клиент будет немедленно перепроверить информацию с сервера, чтобы сервер почти всегда будут доступны ожидающий запрос, который он может использовать для передавать данные в ответ на событие. В контексте Web/AJAX длительный опрос также известный как программирование кометы.
Длинный опрос сам по себе не является толчком технологии, но могут использоваться в обстоятельства, при которых реальный толчок не возможно.
В основном это принудительно возвращает запрос на сервер, как только вы получите ответ. Каков наилучший способ сделать это в приложении iphone? Это в конечном итоге должно выполняться в фоновом режиме.
Ответы
Ответ 1
Это точно такой вариант использования, что NSURLConnection sendSynchronousRequest
идеально подходит для:
- (void) longPoll {
//create an autorelease pool for the thread
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
//compose the request
NSError* error = nil;
NSURLResponse* response = nil;
NSURL* requestUrl = [NSURL URLWithString:@"http://www.mysite.com/pollUrl"];
NSURLRequest* request = [NSURLRequest requestWithURL:requestUrl];
//send the request (will block until a response comes back)
NSData* responseData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response error:&error];
//pass the response on to the handler (can also check for errors here, if you want)
[self performSelectorOnMainThread:@selector(dataReceived:)
withObject:responseData waitUntilDone:YES];
//clear the pool
[pool drain];
//send the next poll request
[self performSelectorInBackground:@selector(longPoll) withObject: nil];
}
- (void) startPoll {
//not covered in this example: stopping the poll or ensuring that only 1 poll is active at any given time
[self performSelectorInBackground:@selector(longPoll) withObject: nil];
}
- (void) dataReceived: (NSData*) theData {
//process the response here
}
В качестве альтернативы вы можете использовать async-I/O и делегировать обратные вызовы для выполнения того же, но в этом случае это будет действительно глупо.
Ответ 2
Длительный опрос делает запрос на чтение сервером, сервер получает запросы, обнаруживает, что вам ничего не интересно отправить, а вместо того, чтобы ничего не возвращать или "пусто", вместо этого он удерживает запрос до тех пор, пока что-то Интересно. Как только он что-то находит, он записывает в сокет, и клиент получает данные.
Детально, что в течение всего этого времени, используя универсальное программирование сокетов, клиент блокируется и висит на вызове чтения сокетов.
Есть два способа справиться с этим (ну, три, если вы не против застревать в основном потоке в течение нескольких секунд, но не считайте это).
-
Поместите код обработки сокета в поток. В этом случае весь процесс сокета находится в независимом потоке внутри программы, поэтому он с радостью сидит за чтением, ожидая ответа.
-
Используйте асинхронную обработку сокетов. В этом случае считывание сокетов НЕ блокирует основной поток. Вместо этого вы передаете функции обратного вызова, которые реагируют на активность в сокете, а затем идут по вашему веселью. На Mac есть CFSocket, который предоставляет такую функциональность. Он генерирует собственный поток и управляет соединением сокета с помощью select (2).
Это неплохая статья о CFSocket.
CFSocket хорошо вписывается в идиому Mac о передаче сообщений и событиях, и, вероятно, вы должны смотреть на эту работу. Существует также оболочка класса Obj-C, построенная на CFSocket, называемая ULNetSocket (ранее NetSocket).