- Сокеты¶
- Принципы сокетов¶
- Основные функции¶
- socket()¶
- listen()¶
- accept()¶
- connect()¶
- Передача данных¶
- Сокеты Беркли
- Содержание
- Интерфейс сокета Беркли
- Заголовочные файлы
- Структуры
- Функции
- socket()
- Прототип
- gethostbyname() и gethostbyaddr()
- Прототипы
- connect()
- Прототип
- Прототип
- listen()
- Прототип
- accept()
- Прототип
- Дополнительные параметры для сокетов
- Блокирующие и неблокирующие сокеты
- Передача данных
- Высвобождение ресурсов
- Пример клиента и сервера, использующих TCP
- Сервер
- Клиент
- Пример клиента и сервера, использующие UDP
- Сервер
- Клиент
- См. также
- Ссылки
- Полезное
- Смотреть что такое «Сокеты Беркли» в других словарях:
Сокеты¶
Сокеты (англ. socket — разъём) — название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения.
Принципы сокетов¶
Каждый процесс может создать слушающий сокет (серверный сокет) и привязать его к какому-нибудь порту операционной системы (в UNIX непривилегированные процессы не могут использовать порты меньше 1024). Слушающий процесс обычно находится в цикле ожидания, то есть просыпается при появлении нового соединения. При этом сохраняется возможность проверить наличие соединений на данный момент, установить тайм-аут для операции и т.д.
Каждый сокет имеет свой адрес. ОС семейства UNIX могут поддерживать много типов адресов, но обязательными являются INET-адрес и UNIX-адрес. Если привязать сокет к UNIX-адресу, то будет создан специальный файл (файл сокета) по заданному пути, через который смогут сообщаться любые локальные процессы путём чтения/записи из него (см. Доменный сокет Unix). Сокеты типа INET доступны из сети и требуют выделения номера порта.
Обычно клиент явно подсоединяется к слушателю, после чего любое чтение или запись через его файловый дескриптор будут передавать данные между ним и сервером.
Основные функции¶
Общие | |
Socket | Создать новый сокет и вернуть файловый дескриптор |
Send | Отправить данные по сети |
Receive | Получить данные из сети |
Close | Закрыть соединение |
Серверные | |
Bind | Связать сокет с IP-адресом и портом |
Listen | Объявить о желании принимать соединения. Слушает порт и ждет когда будет установлено соединение |
Accept | Принять запрос на установку соединения |
Клиентские | |
Connect | Установить соединение |
socket()¶
Создаёт конечную точку соединения и возвращает файловый дескриптор. Принимает три аргумента:
domain указывающий семейство протоколов создаваемого сокета
- AF_INET для сетевого протокола IPv4
- AF_INET6 для IPv6
- AF_UNIX для локальных сокетов (используя файл)
type
- SOCK_STREAM (надёжная потокоориентированная служба (сервис) или потоковый сокет)
- SOCK_DGRAM (служба датаграмм или датаграммный сокет)
- SOCK_RAW (Сырой сокет — сырой протокол поверх сетевого уровня).
protocol
Протоколы обозначаются символьными константами с префиксом IPPROTO_* (например, IPPROTO_TCP или IPPROTO_UDP). Допускается значение protocol=0 (протокол не указан), в этом случае используется значение по умолчанию для данного вида соединений.
Функция возвращает −1 в случае ошибки. Иначе, она возвращает целое число, представляющее присвоенный дескриптор.
Пример на Python
Связывает сокет с конкретным адресом. Когда сокет создается при помощи socket(), он ассоциируется с некоторым семейством адресов, но не с конкретным адресом. До того как сокет сможет принять входящие соединения, он должен быть связан с адресом. bind() принимает три аргумента:
- sockfd — дескриптор, представляющий сокет при привязке
- serv_addr — указатель на структуру sockaddr, представляющую адрес, к которому привязываем.
- addrlen — поле socklen_t, представляющее длину структуры sockaddr.
Возвращает 0 при успехе и −1 при возникновении ошибки.
Пример на Python
Автоматическое получение имени хоста.
listen()¶
Подготавливает привязываемый сокет к принятию входящих соединений. Данная функция применима только к типам сокетов SOCK_STREAM и SOCK_SEQPACKET. Принимает два аргумента:
- sockfd — корректный дескриптор сокета.
- backlog — целое число, означающее число установленных соединений, которые могут быть обработаны в любой момент времени. Операционная система обычно ставит его равным максимальному значению.
После принятия соединения оно выводится из очереди. В случае успеха возвращается 0, в случае возникновения ошибки возвращается −1.
Пример на Python
accept()¶
Используется для принятия запроса на установление соединения от удаленного хоста. Принимает следующие аргументы:
- sockfd — дескриптор слушающего сокета на принятие соединения.
- cliaddr — указатель на структуру sockaddr, для принятия информации об адресе клиента.
- addrlen — указатель на socklen_t, определяющее размер структуры, содержащей клиентский адрес и переданной в accept(). Когда accept() возвращает некоторое значение, socklen_t указывает сколько байт структуры cliaddr использовано в данный момент.
Функция возвращает дескриптор сокета, связанный с принятым соединением, или −1 в случае возникновения ошибки.
Пример на Python
connect()¶
Устанавливает соединение с сервером.
Некоторые типы сокетов работают без установления соединения, это в основном касается UDP-сокетов. Для них соединение приобретает особое значение: цель по умолчанию для посылки и получения данных присваивается переданному адресу, позволяя использовать такие функции как send() и recv() на сокетах без установления соединения.
Загруженный сервер может отвергнуть попытку соединения, поэтому в некоторых видах программ необходимо предусмотреть повторные попытки соединения.
Возвращает целое число, представляющее код ошибки: 0 означает успешное выполнение, а −1 свидетельствует об ошибке.
Пример на Python
Передача данных¶
Для передачи данных можно пользоваться стандартными функциями чтения/записи файлов read и write, но есть специальные функции для передачи данных через сокеты:
Нужно обратить внимание, что при использовании протокола TCP (сокеты типа SOCK_STREAM) есть вероятность получить меньше данных, чем было передано, так как ещё не все данные были переданы, поэтому нужно либо дождаться, когда функция recv возвратит 0 байт, либо выставить флаг MSG_WAITALL для функции recv, что заставит её дождаться окончания передачи. Для остальных типов сокетов флаг MSG_WAITALL ничего не меняет (например, в UDP весь пакет = целое сообщение).
send, sendto — отправка данных.
Источник
Сокеты Беркли
Сокеты Беркли — интерфейс программирования приложений (API), представляющий собой библиотеку для разработки приложений на языке Си с поддержкой межпроцессного взаимодействия (IPC), часто применяемый в компьютерных сетях.
Сокеты Беркли (также известные как API сокетов BSD), впервые появились как API в операционной системе 4.2BSD Unix (выпущенной в 1983 году). Тем не менее, только в 1989 году Калифорнийский университет в Беркли смог начать выпускать версии операционной системы и сетевой библиотеки без лицензионных ограничений AT&T, действующих в защищённой авторским правом Unix.
API сокетов Беркли сформировал de facto стандарт абстракции для сетевых сокетов. Большинство прочих языков программирования используют интерфейс, схожий с API языка Си.
API Интерфейса транспортного уровня (TLI), основанный на STREAMS, представляет собой альтернативу сокетному API. Тем не менее, API сокетов Беркли значительно преобладает в популярности и количестве реализаций.
Содержание
Интерфейс сокета Беркли
Интерфейс сокета Беркли — API, позволяющий реализацию взаимодействия между компьютерами или между процессами на одном компьютере. Данная технология может работать со множеством различных устройств ввода/вывода и драйверов, несмотря на то, что их поддержка зависит от реализации операционной системы. Подобная реализация интерфейса лежит в основе TCP/IP, благодаря чему считается одной из фундаментальных технологий, на которых основывается Интернет. Технология сокетов впервые была разработана в Калифорнийском университете Беркли для применения на Юникс-системах. Все современные операционные системы имеют ту или иную реализацию интерфейса сокетов Беркли, так как это стало стандартным интерфейсом для подключения к сети Интернет.
Программисты могут получать доступ к интерфейсу сокетов на трёх различных уровнях, наиболее мощным и фундаментальным из которых является уровень сырых сокетов. Довольно небольшое число приложений нуждается в ограничении контроля над исходящими соединениями, реализуемыми ими, поэтому поддержка сырых сокетов задумывалась быть доступной только на компьютерах, применяемых для разработки на основе технологий, связанных с Интернет. Впоследствии, в большинстве операционных систем была реализована их поддержка, включая Windows XP.
Заголовочные файлы
Программная библиотека сокетов Беркли включает в себя множество связанных заголовочных файлов. В их числе:
Базовые функции сокетов BSD и структуры данных. Семейства адресов/протоколов PF_INET и PF_INET6. Широко используются в сети Интернет, включают в себя IP-адреса, а также номера портов TCP и UDP. Семейство адресов PF_UNIX/PF_LOCAL. Используется для локального взаимодействия между программами, запущенными на одном компьютере. В компьютерных сетях не применяется. Функции для работы с числовыми IP-адресами. Функции для преобразования протокольных имен и имен хостов в числовые адреса. Используется локальные данные аналогично DNS.
Структуры
- sockaddr — обобщённая структура адреса, к которой, в зависимости от используемого семейства протоколов, приводится соответствующая структура, например:
- sockaddr_in
- sockaddr_in6
- in_addr
- in6_addr
Функции
socket()
socket() создаёт конечную точку соединения и возвращает дескриптор. socket() принимает три аргумента:
- domain , указывающий семейство протоколов создаваемого сокета. Например:
- PF_INET для сетевого протокола IPv4 или
- PF_INET6 для IPv6.
- PF_UNIX для локальных сокетов (используя файл).
- type (тип) один из:
- SOCK_STREAM (надёжная потокоориентированная служба (сервис) или потоковый сокет)
- SOCK_DGRAM (служба датаграмм или датаграммный сокет)
- SOCK_SEQPACKET (надёжная служба последовательных пакетов) или
- SOCK_RAW (Сырой сокет — сырой протокол поверх сетевого уровня).
- protocol определяет используемый транспортный протокол. Самые распространённые — это IPPROTO_TCP , IPPROTO_SCTP , IPPROTO_UDP , IPPROTO_DCCP . Эти протоколы указаны в . Значение « 0 » может быть использовано для выбора протокола по умолчанию из указанного семейства ( domain ) и типа ( type ).
Функция возвращает −1 в случае ошибки. Иначе, она возвращает целое число, представляющее присвоенный дескриптор.
Прототип
gethostbyname() и gethostbyaddr()
Функции gethostbyname() и gethostbyaddr() возвращают указатель на объект типа struct hostent , описывающий интернет-узел по имени или по адресу, соответственно. Эта структура содержит или информацию, полученную от сервера имен или произвольные поля из строки в /etc/hosts. Если локальный сервер имен не запущен, то эти подпрограммы просматривают /etc/hosts. Функции принимают следующие аргументы:
- name , определяющий имя хоста. Например: www.wikipedia.org
- addr , определяющий указатель на struct in_addr , содержащую адрес хоста.
- len , определяющий длину в байтах addr .
- type , определяющий тип области адресов хоста. Например: PF_INET
Функции возвращают NULL-указатель в случае ошибки. В этом случае может быть проверена дополнительная целая h_errno для выявления ошибки или неправильного или неизвестного хоста. В противном случае возвращается корректная struct hostent * .
Прототипы
connect()
connect() Возвращает целое число, представляющее код ошибки: 0 означает успешное выполнение, а −1 свидетельствует об ошибке.
Некоторые типы сокетов работают без установления соединения, это в основном касается UDP-сокетов. Для них соединение приобретает особое значение: цель по умолчанию для посылки и получения данных присваивается переданному адресу, позволяя использовать такие функции как send() и recv() на сокетах без установления соединения.
Загруженный сервер может отвергнуть попытку соединения, поэтому в некоторых видах программ необходимо предусмотреть повторные попытки соединения.
Прототип
bind() связывает сокет с конкретным адресом. Когда сокет создается при помощи socket() , он ассоциируется с некоторым семейством адресов, но не с конкретным адресом. До того как сокет сможет принять входящие соединения, он должен быть связан с адресом. bind() принимает три аргумента:
- sockfd — дескриптор, представляющий сокет при привязке
- serv_addr — указатель на структуру sockaddr , представляющую адрес, к которому привязываем.
- addrlen — поле socklen_t , представляющее длину структуры sockaddr .
Возвращает 0 при успехе и −1 при возникновении ошибки.
Прототип
listen()
listen() подготавливает привязываемый сокет к принятию входящих соединений. Данная функция применима только к типам сокетов SOCK_STREAM и SOCK_SEQPACKET . Принимает два аргумента:
- sockfd — корректный дескриптор сокета.
- backlog — целое число, означающее число установленных соединений, которые могут быть обработаны в любой момент времени. Операционная система обычно ставит его равным максимальному значению.
После принятия соединения оно выводится из очереди. В случае успеха возвращается 0, в случае возникновения ошибки возвращается −1.
Прототип
accept()
accept() используется для принятия запроса на установление соединения от удаленного хоста. Принимает следующие аргументы:
- sockfd — дескриптор слушающего сокета на принятие соединения.
- cliaddr — указатель на структуру sockaddr , для принятия информации об адресе клиента.
- addrlen — указатель на socklen_t , определяющее размер структуры, содержащей клиентский адрес и переданной в accept() . Когда accept() возвращает некоторое значение, socklen_t указывает сколько байт структуры cliaddr использовано в данный момент.
Функция возвращает дескриптор сокета, связанный с принятым соединением, или −1 в случае возникновения ошибки.
Прототип
Дополнительные параметры для сокетов
После создания сокета можно задавать для него дополнительные параметры. Вот некоторые из них:
- TCP_NODELAY отключает алгоритм Нэгла (англ.Nagle’s_algorithm)
- SO_KEEPALIVE включает периодические проверки на наличие ‘признаков жизни’, если это поддерживается ОС.
Блокирующие и неблокирующие сокеты
Сокеты Беркли могут работать в одном из двух режимов: блокирующем или неблокирующем. Блокирующий сокет не возвращает контроль пока не отошлет (или пока не получит) все данные, указанные для операции. Это верно лишь для Linux-систем. В других системах, например во FreeBSD, вполне естественно для блокирующего сокета посылать не все данные. Приложение должно проверять возвращаемое значение для отслеживания того, сколько байт было послано/получено и, соответственно, перепосылать необработанную на данный момент информацию [1]. Это может привести к проблемам, если сокет продолжает «слушать»: программа может повиснуть из-за того, что сокет ждет данных, которые могут никогда не прибыть.
Сокет обычно указывается блокирующим или неблокирующим при помощи функций fcntl() или ioctl() .
Передача данных
Для передачи данных можно пользоваться стандартными функциями чтения/записи файлов read и write , но есть специальные функции для передачи данных через сокеты:
Нужно обратить внимание, что при использовании протокола TCP (сокеты типа SOCK_STREAM ) есть вероятность получить меньше данных, чем было передано, так как ещё не все данные были переданы, поэтому нужно либо дождаться, когда функция recv возвратит 0 байт, либо выставить флаг MSG_WAITALL для функции recv , что заставит её дождаться окончания передачи. Для остальных типов сокетов флаг MSG_WAITALL ничего не меняет (например, в UDP весь пакет = целое сообщение). Смотри также главу «Блокирующие и неблокирующие сокеты».
Высвобождение ресурсов
Система не освобождает ресурсы, выделенные при вызове socket() , пока не произойдет вызова close() . Это особенно важно в случае, если вызов connect() прошёл неудачно и может быть повторен. Каждый вызов socket() должен иметь соответствующий вызов close() во всех возможных путях исполнения. Необходимо добавлять заголовочный файл для поддержки функции закрытия.
Результатом выполнения системного вызова close() является только обращение к интерфейсу для закрытия сокета, а не закрытие самого сокета. Это является командой для ядра закрыть сокет. Иногда, на серверной стороне сокет может перейти в режим ожидания TIME_WAIT до 4 минут.[2]
Пример клиента и сервера, использующих TCP
TCP реализует концепцию соединения. Процесс создаёт TCP-сокет вызовом функции socket() с параметрами PF INET или PF_INET6 , а также SOCK_STREAM (Потоковый сокет) и IPPROTO_TCP .
Сервер
Создание простейшего TCP-сервера состоит из следующих шагов:
- Создание TCP-сокетов вызовом функции socket() .
- Привязывание сокета к прослушиваемому порту вызовом функции bind() . Перед вызовом bind() программист должен объявить структуру sockaddr_in , очистить её (при помощи memset() ), затем sin_family ( PF_INET или PF_INET6 ) и заполнить поля sin_port (прослушиваемый порт, указать в виде последовательности байтов). Преобразование short int в порядок байтов может быть выполнено при помощи вызова функции htons() (сокращение от «от хоста в сеть»).
- Подготовка сокета к прослушиванию на предмет соединений (создание прослушиваемого сокета) при помощи вызова listen() .
- Принятие входящих соединений через вызов accept() . Это блокирует сокет до получения входящего соединения, после чего возвращает дескриптор сокета для принятого соединения. Первоначальный дескриптор остаётся прослушиваемым дескриптором, а accept() может быть вызван вновь для этого сокета в любое время (пока он закрыт).
- Соединение с удаленным хостом, которое может быть создано при помощи send() и recv() или write() и read() .
- Итоговое закрытие каждого открытого сокета, который больше не нужен, происходит при помощи close() . Необходимо отметить, что если были любые вызовы fork() , то каждый процесс должен закрыть известные ему сокеты (ядро отслеживает количество процессов, имеющих открытый дескриптор), а кроме того, два процесса не должны использовать один и тот же сокет в одно время.
Клиент
Создание TCP-клиента происходит следующим образом:
- Создание TCP-сокета вызовом socket() .
- Соединение с сервером при помощи connect() , передача структуры sockaddr_in с sin_family с указанными PF_INET или PF_INET6 , sin_port для указания порта прослушивания (в байтовом порядке), и sin_addr для указания IPv4 или IPv6 адреса прослушиваемого сервера (также в байтовом порядке).
- Взаимодействие с сервером при помощи send() и recv() или write() и read() .
- Завершение соединения и сброс информации при вызове close() . Аналогично, если были какие-либо вызовы fork() , каждый процесс должен закрыть ( close() ) сокет.
Пример клиента и сервера, использующие UDP
UDP основывается на протоколе без установления соединений, то есть протокол, не гарантирующий доставку информации. UDP-пакеты могут приходить не в указанном порядке, дублироваться и приходить более одного раза, или даже не доходить до адресата вовсе. Из-за этих минимальных гарантий, UDP значительно уступает протоколу TCP. Отсутствие установки соединений означает отсутствие потоков или соединений между двумя хостами, так как вместо этого данные прибывают в датаграммах (Датаграммный сокет).
Адресное пространство UDP, область номеров UDP-портов (в терминологии ISO — TSAP) полностью отделены от TCP-портов.
Сервер
Код может создавать UDP-сервер на порту 7654 следующим образом:
bind() связывает сокет с парой адрес/порт.
Такой бесконечный цикл получает все UDP-датаграммы, приходящие на порт 7654, при помощи recvfrom(). Функция использует параметры:
- сокет
- указатель на буфер данных
- размер буфера
- флаги (аналогично при чтении или других сокетных функциях получения)
- адресная структура отправителя
- длина адресной структуры отправителя.
Клиент
Простейшая демонстрация отправки UDP-пакета, содержащего «Привет!» на адрес 127.0.0.1 порт 7654 выглядит примерно так:
См. также
- Компьютерная сеть
- Интернет-сокет
- Unix domain socket
- Winsock — API, основанный на сокетах Беркли, но предназначенный для создания распределённых приложений на платформе Microsoft Windows
Ссылки
Определение стандарта «де юре» интерфейса сокетов, содержащееся в стандарте POSIX, более известное как:
Wikimedia Foundation . 2010 .
Полезное
Смотреть что такое «Сокеты Беркли» в других словарях:
Сокет (программный интерфейс) — У этого термина существуют и другие значения, см. Сокет. Сокеты (англ. socket углубление, гнездо, разъём) название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на… … Википедия
Программирование сетевых задач — В области компьютеризации понятие программирования сетевых задач или иначе называемого сетевого программирования (англ. network programming), довольно сильно схожего с понятиями программирование сокетов и клиент серверное программирование,… … Википедия
Unix domain socket — (Доменный сокет Unix) или IPC сокет (сокет межпроцессного взаимодействия) конечная точка обмена данными, схожая с Интернет сокетом, но не использующая сетевой протокол для взаимодействия (обмена данными). Он используется в операционных системах,… … Википедия
Сырой сокет — интерфейс программирования приложений (API), разновидность сокетов Беркли, позволяющий собирать TCP/IP пакеты, контролируя каждый бит заголовка и отправляя в сеть нестандартные пакеты. Пример Создание сокета. Код на языке Си . int i32SocketFD … Википедия
UNIX — Генеалогическое древо UNIX систем UNIX (читается юникс) семейство переносимых, многозадачных и многопользовательских … Википедия
UX — Генеалогическое древо UNIX систем UNIX (читается юникс) группа переносимых, многозадачных и многопользовательских операционных систем. Первая система UNIX была разработана в 1969 г. в подразделении Bell Labs компании AT T. С тех пор было создано … Википедия
Unix — Генеалогическое древо UNIX систем UNIX (читается юникс) группа переносимых, многозадачных и многопользовательских операционных систем. Первая система UNIX была разработана в 1969 г. в подразделении Bell Labs компании AT T. С тех пор было создано … Википедия
ЮНИКС — Генеалогическое древо UNIX систем UNIX (читается юникс) группа переносимых, многозадачных и многопользовательских операционных систем. Первая система UNIX была разработана в 1969 г. в подразделении Bell Labs компании AT T. С тех пор было создано … Википедия
Юникс — Генеалогическое древо UNIX систем UNIX (читается юникс) группа переносимых, многозадачных и многопользовательских операционных систем. Первая система UNIX была разработана в 1969 г. в подразделении Bell Labs компании AT T. С тех пор было создано … Википедия
Интерфейс транспортного уровня — В области проектирования компьютерных сетей Интерфейс транспортного уровня (от англ. Transport Layer Interface) (TLI) был сетевым API, поддерживаемым AT T UNIX System V Release 3 (SVR3) и Release 4 (SVR4). TLI был двойником (но в System V)… … Википедия
Источник