Открыть сервисСервис

Сокет в компьютерных сетях

Сокет (англ. socket, «гнездо», «разъём») — программный интерфейс (API) для организации межпроцессного и сетевого взаимодействия, а также абстракция конечной точки двунаправленного канала связи между процессами. В операционных системах семейства UNIX и Linux сокет представляет собой файловый дескриптор, через который программа может читать и записывать данные, передаваемые по сети или между процессами на одном компьютере. Понятие было введено в 1983 году в системе 4.2BSD и с тех пор стало стандартом для сетевого программирования на платформах UNIX, Linux, Windows и других.

История

Сокеты появились в системе 4.2BSD, разработанной в Калифорнийском университете в Беркли. До этого сетевые программы использовали более низкоуровневые интерфейсы, привязанные к конкретным протоколам. Идея сокетов заключалась в создании единого абстрактного механизма, позволяющего работать с разными протоколами (TCP, UDP, IPX и др.) через одинаковый набор системных вызовов. Позднее сокетный API был стандартизирован в стандарте POSIX и стал частью спецификации IEEE Std 1003.1 (POSIX.1). В Windows аналогичный интерфейс реализован в виде библиотеки Winsock.

Классификация

Сокеты классифицируются по нескольким признакам.

По домену (семейству адресов):

  • AF_INET — IPv4, наиболее распространённый вариант;
  • AF_INET6 — IPv6;
  • AF_UNIX (AF_LOCAL) — межпроцессное взаимодействие на одном компьютере через файловую систему;
  • AF_NETLINK — общение с ядром Linux;
  • AF_PACKET — работа на уровне сетевых кадров.

По типу:

  • SOCK_STREAM — потоковые сокеты, работающие поверх TCP (или протокола UNIX-сокетов). Обеспечивают надёжную доставку, порядок и контроль потока.
  • SOCK_DGRAM — датаграммные сокеты поверх UDP. Не гарантируют доставку и порядок пакетов, но работают быстрее.
  • SOCK_RAW — «сырые» сокеты, предоставляющие доступ к пакетам нижележащего уровня (требуют повышенных привилегий).
  • SOCK_SEQPACKET — последовательные датаграммные сокеты с сохранением границ сообщений.

Устройство и принцип работы

Работа с сокетами строится на последовательности системных вызовов. Серверная сторона выполняет следующие шаги:

  1. socket() — создание сокета с указанием домена, типа и протокола.
  2. bind() — привязка сокета к локальному адресу и порту.
  3. listen() — переход в режим прослушивания входящих соединений (для потоковых сокетов).
  4. accept() — принятие входящего соединения, в результате которого создаётся новый сокет для общения с конкретным клиентом.
  5. read() / write() (или recv() / send()) — приём и передача данных.
  6. close() — закрытие сокета.

Клиентская сторона обычно выполняет socket(), затем connect() для установления соединения с сервером, после чего читает и пишет данные и закрывает сокет.

Для датаграммных сокетов вызовы listen() и accept() не используются: вместо них применяются sendto() и recvfrom(), позволяющие указывать адрес получателя при каждой отправке.

Мультиплексирование

Когда процессу нужно обслуживать несколько соединений одновременно, применяется мультиплексирование. В Linux и UNIX доступны механизмы select(), poll() и epoll(), в Windows — select() и комплект ввода-вывода (IOCP). Эти механизмы позволяют одним потоком отслеживать готовность нескольких сокетов к чтению или записи, что лежит в основе большинства высокопроизводительных сетевых серверов.

Применение

Сокеты являются основой большинства сетевых протоколов и приложений:

  • веб-серверы и клиенты (HTTP/HTTPS поверх TCP-сокетов);
  • почтовые системы (SMTP, POP3, IMAP);
  • системы доменных имён (DNS);
  • удалённое управление (SSH, RDP);
  • стриминг медиа;
  • протоколы мгновенных сообщений;
  • клиент-серверные и многопользовательские игры.

Межпроцессное взаимодействие через UNIX-сокеты широко используется в Linux-системах: например, systemd, X Window System и многие демонсы общаются именно через них.

Сокеты в разных языках программирования

В языке C сокетный API предоставляется библиотекой libc. В Python работа с сокетами реализована в модуле socket стандартной библиотеки. В Java используется класс java.net.Socket и java.nio.channels.ServerSocketChannel. В Go стандартный пакет net предоставляет высокоуровневую обёртку над сокетами. В Node.js сокеты доступны через модуль net и dgram.

Интересные факты

  • В Linux сокеты реализованы как файловые дескрипторы, поэтому их можно передавать между процессами через механизм передачи файловых дескрипторов (SCM_RIGHTS).
  • Понятие «сокет» иногда используется в разговорной речи программистов для обозначения IP-адреса в паре с номером порта, например «127.0.0.1:8080».
  • UNIX-сокеты работают быстрее TCP-сокетов на localhost, так как не проходят полный сетевой стек.

Источники:

  • «UNIX Network Programming, Volume 1: Networking APIs» — W. Richard Stevens
  • «The Linux Programming Interface» — Michael Kerrisk
  • POSIX.1-2017 (IEEE Std 1003.1)
  • Документация Linux man-pages: socket(2), bind(2), listen(2), accept(2)
  • RFC 793 (Transmission Control Protocol)
Заметили ошибку или не согласны с информацией в статье? Напишите нам support@bfometr.ru