目标C中的长轮询

时间:2011-06-10 00:26:28

标签: iphone objective-c ipad

我有一个使用API​​在网站上获取实时更新的应用程序。他们使用他们所谓的long-polling technique

  

长轮询是一种变体   传统的民意调查技术   允许模拟信息   从服务器推送到客户端。同   长轮询,客户要求   来自服务器的信息   与普通民意调查类似的方式。然而,   如果服务器没有   为客户提供的信息,   而不是发送空响应,   服务器保存请求并等待   有些信息可供使用。   一旦信息可用   (或在适当的超时后),a   完整的回复发送到   客户。那时客户通常会   立即重新请求信息   从服务器,使服务器   几乎总会有一个可用的   等待它可以使用的请求   提供数据以响应事件。   在web / AJAX上下文中,长轮询是   也称为Comet编程。

     

长期民意调查本身并不是一种推动力   技术,但可以使用   真正推动不是的情况   可能的。

基本上,这会在您收到回复后强制将请求发回服务器。在iPhone应用程序中执行此操作的最佳方法是什么?这最终必须在后台运行。

2 个答案:

答案 0 :(得分:15)

这正是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
}

或者,你可以使用异步I / O和委托回调来完成同样的事情,但在这种情况下这确实很愚蠢。

答案 1 :(得分:5)

长轮询正在向服务器发出读取请求,服务器获取请求,发现没有什么东西可以发送给你,而不是什么也不返回,或者“空”,它反而坚持请求有趣的出现了。一旦找到了什么,就会写入套接字,客户端会收到数据。

详细说明,在整个过程中,使用通用套接字编程,客户端被阻塞并挂在套接字读取调用上。

有两种方法可以解决这个问题(好吧,如果你不介意在主线程上停留几秒钟就会有三种方法,但是我们不计算那个)。

  1. 将套接字处理代码放在一个线程中。在这种情况下,整个套接字进程位于程序中的一个独立线程中,因此它很快就会停留在等待响应的读取上。

  2. 使用异步套接字处理。在这种情况下,您的套接字读取不会阻止主线程。相反,你传入回调函数,响应套接字上的活动,然后以你的快乐方式。在Mac上,有CFSocket公开了这种功能。它产生自己的线程,并使用select(2)管理套接字连接。

  3. This是一个很好的小帖子,谈论CFSocket。

    CFSocket非常适合消息传递和事件的Mac习惯用法,可能就是你应该在做这类工作时看到的。还有一个基于CFSocket构建的Obj-C类包装器,名为ULNetSocket(以前称为NetSocket)。