Можно ли закрыть сокет? из другого потока, когда происходит отправка / запись по тому же сокету?

Может ли сокет быть закрыт из другого потока, когда происходит отправка / запись по тому же сокету?

Предположим, что один поток блокирует вызов recv, а другой поток закрывает этот сокет, будет ли поток в вызове recv знаете об этом и смело выходите?

Я хотел бы знать, будет ли поведение различаться в разных ОС / платформах. Если да, как он будет вести себя в Solaris?

13
задан Jay 28 August 2010 в 06:24
поделиться

2 ответа

Я не знаком с реализацией сетевого стека Solaris, но приведу свою теорию/объяснение того, почему он должен быть безопасным.

  • Поток A выполняет какой-либо блокирующий системный вызов, скажем, read(2) для данного сокета. В буфере приема сокета нет данных, поэтому поток A снимается с процессора и помещается в очередь ожидания для этого сокета. Здесь не инициируются никакие события сетевого стека, состояние соединения (при условии, что TCP) не изменилось.
  • Поток B выдает close(2) на сокете. Хотя структура сокета ядра должна быть заблокирована, пока поток B обращается к ней, ни один другой поток не удерживает эту блокировку (поток A снял блокировку, когда он был переведен в режим ожидания). Предполагая, что в буфере отправки сокета нет необработанных данных, отправляется пакет FIN, и соединение переходит в состояние FIN WAIT 1 (опять же я предполагаю, что здесь TCP, см. состояние соединения диаграмма)
  • Я предполагаю, что изменение состояния подключения к сокету вызовет пробуждение для всех потоков, заблокированных в данном сокете. То есть поток A перейдет в рабочее состояние и обнаружит, что соединение закрывается. Ожидание может быть введено повторно, если другая сторона не отправила свой собственный FIN, или в противном случае системный вызов вернется с eof.

В любом случае внутренние структуры ядра будут защищены от несанкционированного одновременного доступа. Это не означает, что рекомендуется выполнять ввод-вывод через сокеты из нескольких потоков. Я бы посоветовал обратить внимание на неблокирующие сокеты, конечные автоматы и фреймворки вроде libevent.

3
ответ дан 2 December 2019 в 01:09
поделиться

Да, можно закрыть сокет из другого потока. Любые заблокированные/занятые потоки, использующие этот сокет, сообщат об соответствующей ошибке.

0
ответ дан 2 December 2019 в 01:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: