@Igorello74

Что делает socket, чтобы выкинуть POLLOUT в select.poll?

Предыстория
Решил написать неблокирующий микросервер на esp32 (— ограниченные ресурсы) с использованием microPython, но особой роли это не играет, так как API socket'ов тут +/- такой же, как в CPython.

Добрый день!

A. В сокетах я новичок, поэтому мне не совсем ясно, при каких обстоятельствах socket выбрасывает в select.poll событие POLLOUT. Я имею в виду: вот зарегистрировал я socket (который получил от sock.accept()) в poller'е на серверной стороне, при удобной возможности произвожу poller.poll(), и оказывается, что socket готов что-либо принять. Как так? В моём представлении о сокетах:
  1. Клиент отправляет серверу запрос на соединение (sock.connect()).
  2. Сервер принимает запрос (sock.accept())
  3. Сервер по socket'у, полученному accept'ом, принимает данные (sock.recv())
  4. Обработав данные, сервер формирует ответ и отсылает его по socket'у (sock.send()

Вопрос:
где здесь клиент запрашивает ответ, тем самым заставляя socket выкинуть POLLOUT в poll'е?

B. Тоже о сокетах в poll'е. Правильно ли я понимаю, что вызов poller.poll() может вернуть в качестве события что-то смешанное, наподобие POLLOUT | POLLERR? Таким образом, чтобы классифицировать каждый дескриптор, нужно делать что-то типа: result_event & POLLOUT == POLLOUT?

Заранее спасибо!
P.S.
Если вы считаете, что названную задачу можно было бы решить менее заморочным / более рациональным способом, пожалуйста, дайте мне знать.
P.P.S.
selectors здесь нет.
  • Вопрос задан
  • 34 просмотра
Решения вопроса 1
@javedimka
Хочу сока
Вопрос: где здесь клиент запрашивает ответ, тем самым заставляя socket выкинуть POLLOUT в poll'е?

Это работает не так, с чего бы клиент должен запрашивать ответ? Есть возможность запись в сокет без блокировки, поэтому POLLOUT. Если использовать твое представление о сокетах, в котором обмен данными очень похоже на обмен по HTTP - то нет нужды регистрировать POLLOUT пока не сформируешь ответ. Его если и надо регистрировать, то только если хочешь что-то отправить. А сама "работа" с сокетами зависит от используемых протоколов.
Можно вообще забить на отслеживание события POLLOUT и при отправке данных используя try/except блок которым обёрнут `socket.send` отслеживать EAGAIN/EWOULDBLOCK код ошибки в эксепшене, если возник такой - пытаться отправить снова на следующем лупе - меньше возни и ни на что не особо не влияет (при условии, что клиент данные из сокета читает)
А можно скомбинировать подход. Изначально POLLOUT не отслеживается, если есть данные на отправку - попытаться отправить, если не все данные были отправлены - регистрировать POLLOUT, когда событие придет - отправить оставшееся, если снова не все данные были отправлены - снова ждать POLLOUT

чтобы классифицировать каждый дескриптор, нужно делать что-то типа: result_event & POLLOUT == POLLOUT?

Да
result_event & POLLOUT
или например
result_event & (POLLERR|POLLHUP|POLLNVAL)

selectors здесь нет.

модуль selectors это абстракция над поллингом, я, конечно, не уверен и что внутри либы уже не особо помню, но возможно, если просто скопировать код либы себе - всё заработает без особых проблем.

Неблокирующий сервис можно написать на тредах - хорошо если запросы быстрые и клиентов не очень много
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы