LINUX.ORG.RU

Сообщения IECTA

 

Расскажите в деталях как пользоваться неблокирующими сокетами

Собственно, сабж. Хочу повысить собственный навык network programming до уровня, достаточно для написания веб сервера, принимающего множество подключений.

Что удалось понять самостоятельно:

  1. Использование блокирующих сокетов и запись/чтение через классические read()/write() в потоке для каждого подключения имеет смысл только если сервер не рассчитан на большое кол-во подключения (ибо большое кол-во потоков будет жрать память) в пользу простоты кода.
  2. Использование неблокирующих сокетов имеет смысл если нужно принимать много подключений, и данных оттуда могут поступать не сразу/медленно/с задержкой. Посему можно набрать пачку подключений и потом poll()-ить их.
  3. Создание потока (posix threads) или процесса (fork()) - довольно затратная операция, и потому для отзывчивого и/или производительного сервера есть смысл создавать потоки/процессы заранее, а потом передавать им дескрипторы.
  4. Использование блокирующих вызовов ввода-вывода (т.е. write() и read()) не позволяет добиться информации о ошибках типа «потеря соединения» или «network is unreachable», и потому приходится использовать неблокирующие сокеты и соответствующие вызовы.

Что не удалось понять и требуются пояснения:

  1. Как передать дескриптор уже существующему потоку? Я так понял, что никаких спец. техник не нужно, поток просто должен знать номер и всё.
  2. Для передачи дескриптора уже существующему процессу (который создали при помощи fork()) нужно что-то шаманить с sendmsg(). Дальше я не копал. Судя по всему, этим не особо активно пользуются в современном софте, хотя хз. К слову, я так и не понял чем именно sendmsg() заставляет получить дескриптор в процессе, а не просто передаёт информацию.
  3. Если send() и другие функции из той же семьи возвращают кол-во переданных/полученных байт, то как они могут что-то вернуть, если они сразу возвращают управление? Что они возвращают в таком случае?
  4. Можно ли использовать буфер сразу после того, как send() вернул управление? Если да, то он, получается, сначала копирует буфер в пространство ядра, а потом возвращает управление (т.е. send() всё-таки не мгновенно возвращает, лол). Если нет, то когда можно снова использовать буфер? Нужно poll()-ить и ждать пока poll() вернёт результат по соответствующему дескриптору?
  5. Если poll()-ить менее пары десятков дескрипторов, можно ли забить болт на epoll() или kqueue()?
  6. Есть ли какой-то годный туториал (от простого к сложному, можно и на английском), который бы посвятил бы во всякие тонкости типа тех, которые будут в следующем пункте:
  7. Если poll() сообщает, что есть входящие данные по дескриптору, но чтение их возвращает 0, означает ли это, что удалённый хост просто сделал close()?
  8. Зачем нужен shutdown(), если есть обычный close()?

 , ,

IECTA
()

RSS подписка на новые темы