Почему в iOS не происходит сбой сокета recv при изменении базовой сети?
В iOS, когда у меня есть сокет блокировки с таймаутом, установленным с помощью SO_RCVTIMEO. Когда я изменяю сеть Wi-Fi, к которой подключено устройство, вызовы recv будут соответственно задерживаться, но errno будет сообщаться как EWOULDBLOCK и recv возвращает -1.
Это приводит к тому, что мой внешний цикл обработки снова пытается получить доступ к сокету (так как кажется, что на данный момент данных просто нет), когда это реально невозможно в данный момент, поскольку устройство теперь подключено к другой конечной точке сети.
Если я просто уничтожу сеть в целом, несколько повторных вызовов recv в конечном итоге потерпят неудачу с ETIMEDOUT, после многих EWOULDBLOCK.
Почему это происходит? Разве соединение с сокетом не должно быть разорвано и завершиться с ошибкой с помощью ENETRESET или аналогичной ошибки?
Если у меня нет SO_RCVTIMEO, то при изменении сети WiFi сокет будет блокироваться навсегда. Также нет Буэно.
РЕДАКТИРОВАТЬ: я думаю, что я мог бы просто включить SO_KEEPALIVE на локальном сокете, чтобы определить, когда удаленный сокет перестает отвечать из-за изменения базовой конечной точки сети. Кажется, это тоже не работает.
1 ответ
Я отправлю свой ответ здесь. Оказывается, что при использовании keepalive его необходимо сначала включить для уровня сокета SOL_SOCKET, а также установить интервал keepalive на уровне TCP (уровень IPPROTO_TCP с TCP_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));
Я наткнулся на синтаксис по аналогичному посту.
Можно ли активировать поддержку активности TCP на устройствах Apple iOS?