屏幕锁定后iOS监听套接字变为坏文件描述符

时间:2016-03-19 10:39:58

标签: ios iphone sockets networking tcp

我在我的应用程序中出于某种原因(跨平台相关)使用TCP服务器(仅绑定到127.0.0.1和随机端口)。我使用posix函数select来检查是否有新的tcp连接。它大部分时间工作正常,但是当我:1)按主页按钮,锁定屏幕。 2)解锁屏幕,按App图标立即返回App。

select函数返回,告诉我我可以处理我的服务器套接字,在调用accept函数后,它返回-1,然后我通过{{1}检查SO_ERROR },返回错误getsockopt。代码如下:

EBADF

日志:

//listen fd is already nonblocking
if ((*pa = accept(*ps, addr, len)) != -1){
    printf("after accept %d %d\n", *pa, errno);
    return IO_DONE;
}

printf("after accept error %d %d %d %s\n", *ps, *pa, errno, strerror(errno));

int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (*ps, SOL_SOCKET, SO_ERROR, &error, &len);
if (retval != 0) {
    /* there was a problem getting the error code */
    fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
}

if (error != 0) {
    /* socket has a non zero error status */
    fprintf(stderr, "socket error: %s\n", strerror(error));
}

我的测试设备是iPhone 4s,操作系统版本是iOS 8.4.1

我已经https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/CommonPitfalls/CommonPitfalls.html,我没有发现任何错误。

那么,为什么会发生这种情况以及如何解决?

2 个答案:

答案 0 :(得分:1)

https://github.com/robbiehanson/CocoaHTTPServer/issues/10 我遇到了同样的问题。

应用程序需要观察UIApplicationWillResignActiveNotification和UIApplicationWillEnterForegroundNotification通知,并相应地停止并重新启动服务器。

保留初始服务器端口也很重要,因为webview将无法从其他端口加载资源。“ “

答案 1 :(得分:1)

https://developer.apple.com/library/archive/technotes/tn2277/_index.html

监听插座 在多任务环境中处理监听套接字非常简单:您的应用程序在进入后台时应关闭监听套接字,而在回到前台时应重新打开监听套接字。这样做有两个重要原因:

一旦您的应用进入后台,它可能会被暂停。一旦挂起,就无法正确处理侦听套接字上的传入连接。但是,就内核而言,套接字仍然处于活动状态。如果客户端连接到套接字,则内核将接受该连接,但您的应用程序将无法通过它进行通信。最终客户会放弃,但这可能需要一段时间。 因此,最好在进入后台时关闭侦听套接字,这将导致进入的连接立即被内核拒绝。

如果系统挂起您的应用程序,然后在以后从监听套接字的下方回收资源,则即使恢复后,您的应用程序也将不再监听连接。该应用程序可能会收到通知,也可能不会收到通知,具体取决于它如何管理侦听套接字。通常,通过在应用程序处于后台时关闭侦听套接字来完全避免此问题会更容易。 请记住,当您的应用关闭监听套接字时,它还应该停止该套接字的所有Bonjour注册。