当iOS应用程序进入后台时,TCP和UDP(带组播)连接会发生什么?

7

我创建了两个实验:

实验1:我创建了一个TCP发送器应用和一个TCP接收器应用。

在这个实验中,我在一个iOS设备上启动了TCP发送器,另一个iOS设备上启动了TCP接收器。然后验证它们已经建立连接并发送和接收数据。接着,我将TCP接收器应用程序放到后台。TCP发送器应用程序指示失去连接并崩溃(是的,我是有意这样做的)。

实验2:我创建了一个UDP发送器应用和一个UDP接收器应用。

与上述实验相同,我在一个iOS设备上启动了UDP发送器应用,另一个iOS设备上启动了UDP接收器应用。在UDP接收器应用程序中,我订阅了一个多播组等。我验证UDP接收器应用程序正在接收由UDP发送器应用程序发送到该多播组的数据。然后,我将UDP接收器应用程序放到后台。2分钟后,我让UDP发送器应用程序发送另一段数据。然后,我完全退出UDP发送器应用程序并关闭那个iOS设备。然后,我等待另外2分钟或更长时间,然后从后台启动UDP接收器应用程序。UDP接收器应用程序确实接收到了UDP发送器应用程序在终止之前发送的数据。

在实验1中,我的解释是因为TCP是面向连接的。

在实验2中,我了解到UDP是无连接的。为什么实验2会以我所经历的方式工作?(即使在后台模式下仍然接收数据)

2个回答

13
当您将应用程序置于后台并让其挂起时,发生的一切只是它停止由内核调度。除非强制执行,否则它不会立即断开任何连接或拆除任何套接字。
在您的UDP情况下,内核接收数据包并将其放入内核缓冲区中,等待您的应用程序接收它。由于您的应用程序进程存在但实际上已停止,因此数据将停留在内核缓冲区中。如果获取了太多数据,则会溢出内核缓冲区并被丢弃。否则,您的应用程序可以在再次调度时(如果有的话)接收它。
在TCP情况下,基本上发生相同的事情。
但是(大但是):操作系统始终有权根据内存压力等原因拆除挂起应用程序的套接字。因此,虽然它不一定会毫无理由地这样做,但它可能会这样做。
我不确定为什么您会看到TCP连接很快被切断。可能是因为用于断开TCP连接的内核启发式算法比用于UDP套接字更加积极,因为TCP连接需要更多的状态和更持续的处理。
请参见Technical Note TN2277 Networking and Multitasking

1
顺便提一下,我假设你说的“background”是指“suspended”,因为你没有提到你正在尝试运行一个启用了后台的应用程序(VOIP、音乐等)。除非你采取特殊措施,否则后台对于你的应用程序来说是一个短暂的状态,在进入后台后很快就会被挂起。请参阅苹果iOS应用程序生命周期文档。 - smparkes
非常好的解释!我的想法与您的解释一致,而且那篇技术文章也很好地证实了它。(+1赞)是的,我确实是指挂起而不是后台。顺便说一下:我的TCP发送器崩溃得很快,因为它不断地向接收器发送数据流。 - user523234
如果你使用主线程的阻塞调用发送数据,而目标却没有接收到,iOS会认为你的应用程序无响应并将其关闭,这是有道理的。TCP连接可能仍然正常;它具有流控制来管理缓冲区,但你不能允许主线程被阻塞太久。 - smparkes
很棒的答案!它解释了我在项目中遇到的问题:我在appWillResignActive中向服务器发送数据,服务器立即接收到并立即响应,但iOS应用程序无法立即看到响应;几秒钟后,当我将应用程序带回前台时,在调试日志中转储的第一件事是来自服务器的上述响应。然而,如果我在几分钟而不是几秒钟后将应用程序带回前台,我的应用程序会崩溃-请参见答案中的“大但”。 - 拇指 muzhi.com

0

我的观点是由于操作系统的原因,如果您在Android操作系统上尝试过,这种情况不应该发生,因为IOs对可以在后台工作的内容和不能工作的内容有限制。

根据您所说,我认为这是因为TCP需要更多的资源来发送信息。TCP使用数据流,而UDP使用数据块。问题在于TCP创建更大的数据包,而UDP使用8 kb的数据块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接