【问题标题】:long polling in objective-CObjective-C 中的长轮询
【发布时间】:2011-09-12 03:31:03
【问题描述】:

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

长轮询是 传统的投票技术和 允许模拟信息 从服务器推送到客户端。和 长轮询,客户端请求 来自服务器的信息 类似于普通民意调查的方式。然而, 如果服务器没有任何 可供客户使用的信息, 而不是发送空响应, 服务器持有请求并等待 以获得一些信息。 一旦信息可用 (或在适当的超时后),一个 完整的响应被发送到 客户。然后客户端通常会 立即重新索取资料 从服务器,使服务器 几乎总是有可用的 等待它可以用来的请求 传递数据以响应事件。 在 web/AJAX 上下文中,长轮询是 也称为彗星编程。

长轮询本身不是推送 技术,但可以在下使用 没有真正推动的情况 可能。

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

【问题讨论】:

  • 不清楚您在寻找什么。看来您已经有了这个概念,那么您的问题是什么?
  • 请注意,除非您使用 VoIP、音频流或 GPS,否则这不会在 iOS 的后台运行。否则您的应用将被暂停。

标签: iphone objective-c ipad


【解决方案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
}

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

【讨论】:

  • 在主机发回响应之前,如何阻止NSURLConnectionNSURLErrorTimedOut 失败?使用NSURLConnection 时如何配置长轮询的时长?
  • @Jeremy:This answer 将涵盖这一点。基本上你只需将requestWithUrl: 替换为requestWithURL:cachePolicy:timeoutInterval:,指定一个任意大的超时间隔。
  • 走这条路线比使用异步 NSURLConnection 有什么好处?
  • @hambonious - 更简单的实现(例如,您不必实现任何委托协议)和更直观的控制流是两个好处。在我看来,异步 I/O 确实有点被夸大了。它并不总是比使用同步 I/O“更好”。
  • @David - 不,它实际上不是递归的,因为longPoll 的调用不会等待下一个调用返回,然后才返回自身。它安排下一次调用,然后返回。它基本上是 JavaScript 中 setTimeout() loop 的 Objective-C 等价物。或者等效地,setInterval() call.
【解决方案2】:

长轮询是向服务器发出读取请求,服务器获取请求,发现没有任何感兴趣的内容可以发送给您,而不是返回任何内容或“空”,而是保持请求直到出现某些内容有趣的出现。一旦找到东西,它就会写入套接字,客户端接收数据。

细节是,在这整个时间里,使用通用套接字编程,客户端被阻塞并挂在套接字读取调用上。

有两种方法可以解决这个问题(好吧,如果您不介意在主线程上卡住几秒钟,则可以使用三种方法,但我们不要指望那一种)。

  1. 将套接字处理代码放入线程中。在这种情况下,整个套接字进程都在程序中的一个独立线程中,因此它很高兴地卡在读取等待响应中。

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

This 是一篇关于 CFSocket 的不错的小帖子。

CFSocket 非常适合消息传递和事件处理的 Mac 习惯,并且可能是您在进行此类工作时应该考虑的。还有一个构建在 CFSocket 上的 Obj-C 类包装器,称为ULNetSocket(以前称为 NetSocket)。

【讨论】:

    猜你喜欢
    • 2013-08-08
    • 2011-04-20
    • 2019-05-28
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    • 2013-02-28
    • 2013-09-13
    相关资源
    最近更新 更多