在iOS中,当底层网络发生变化时,为什么socket recv不会失败?

In iOS, why doesn't socket recv fail when the underlying network changes?

在 iOS 中,当我有一个使用 SO_RCVTIMEO 设置超时的阻塞套接字时。当我更改设备连接的 WiFi 网络时,对 recv 的调用将适当超时,但 errno 将报告为 EWOULDBLOCK 和 recv returns -1.

这导致我的外部处理循环尝试再次访问套接字(因为现在似乎没有可用数据),但实际上此时这是不可能的,因为设备现在连接到不同的网络端点.

如果我完全关闭网络,在多次 EWOULDBLOCK 之后,对 recv 的多次重复调用最终会因 ETIMEDOUT 而失败。

为什么会出现这种情况?套接字连接不应该因 ENETRESET 或类似的错误号而中断和失败吗?

如果我没有 SO_RCVTIMEO,那么当 WiFi 网络变化时套接字将永远阻塞。也没有布埃诺。

编辑:我想我可以在本地套接字上启用 SO_KEEPALIVE 来检测远程套接字何时因底层网络端点更改而停止响应。这似乎也不起作用。

我会post 在这里给出我自己的答案。原来在使用keepalive的时候,首先要对socket级别SOL_SOCKET开启,还要在TCP层(IPPROTO_TCP级别与TCP_KEEPALIVE)设置keepalive间隔,为默认通常为 7200 秒(2 小时)。

int on = 1;
int delay = 120;
setsockopt(socket_handle, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
setsockopt(socket_handle, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay));

我遇到了类似 post 的语法。

Is it possible to activate TCP keepalive on Apple iOS devices