Убедитесь, что розетка все еще открыта без блокировки - PullRequest
1 голос
/ 19 апреля 2020

Как проверить, открыт ли сокет TCP без блокировки?

Если я использую usocket, то чтение из потока сокета будет сигнализировать об окончании файла, если сокет закрыт, но будет заблокируйте это иначе, чего я не хочу. Я пытался использовать (listen stream), чтобы заранее проверить, будет ли сокет заблокирован, но (listen) возвращает nil в закрытом сокете, что здесь не помогает. Я также попытался проверить (usocket::state socket), который дает :READ для закрытого сокета, но иногда он также дает :READ для открытого сокета, даже если там ничего нет. Я использую sbcl, поэтому я попытался использовать (sb-bsd-sockets:socket-open-p), но это дает T для закрытого сокета, также не помогает. Единственная команда, которая кажется полезной, это (wait-for-input), а именно она будет возвращаться почти сразу же при вызове в закрытом сокете, даже если задано более длительное время ожидания. В то же время, (listen) все равно будет давать nil, и это вместе указывает на закрытый сокет. Этот способ выглядит довольно хаки sh для меня.

Есть ли лучший способ?

1 Ответ

2 голосов
/ 04 мая 2020

Это конкретно не проблема с Лиспом. Это проблема, присущая самому TCP.

Единственный способ в TCP определить, открыто ли соединение, - это попытаться отправить данные через него или использовать функцию поддержки активности TCP (которая отправляет данные через сокет для you).

Linux, Windows и MacOS имеют опцию сокета SO_KEEPALIVE (см. setsockopt(2), который реализует поддержку активности TCP. Есть и другие связанные сокеты, такие как TCP_KEEPIDLE, TCP_KEEPINTVL и TCP_KEEPCNT, но они не переносимы между операционными системами, и в Лиспе вам будет сложнее найти реальные значения констант препроцессора C и предоставить указатель для option_value аргумент.

Мне не повезло с использованием SO_KEEPALIVE на Linux, и я не пробовал использовать его в любой другой операционной системе.

...