Сокеты Berkeley - это интерфейс прикладного программирования (API) для интернет-сокетов и сокетов домена Unix , используемый для межпроцессного взаимодействия (IPC). Обычно он реализуется как библиотека подключаемых модулей. Он возник в операционной системе 4.2BSD Unix , выпущенной в 1983 году.
Сокет является абстрактным представлением ( ручка ) для локальной конечной точки пути сети связи. API сокетов Беркли представляет его как дескриптор файла ( дескриптор файла ) в философии Unix, который предоставляет общий интерфейс для ввода и вывода потоков данных.
Сокеты Berkeley с небольшими изменениями превратились из стандарта де-факто в компонент спецификации POSIX . Термин « сокеты POSIX» по существу синонимичен сокетам Беркли , но они также известны как сокеты BSD , что свидетельствует о первой реализации в дистрибутиве программного обеспечения Беркли .
История и внедрения
Сокеты Беркли возникли в операционной системе 4.2BSD Unix , выпущенной в 1983 году, как программный интерфейс. Однако только в 1989 году Калифорнийский университет в Беркли не смог выпустить версии операционной системы и сетевой библиотеки, свободные от лицензионных ограничений проприетарной Unix корпорации AT&T .
Все современные операционные системы реализуют версию интерфейса сокетов Беркли. Он стал стандартным интерфейсом для приложений, работающих в Интернете . Даже реализация Winsock для MS Windows, созданная независимыми разработчиками, строго следует стандарту.
В BSD - сокетов API написан на языке программирования Си . Большинство других языков программирования предоставляют аналогичные интерфейсы, обычно написанные в виде библиотеки-оболочки на основе C API. [1]
Сокеты BSD и POSIX
По мере развития API сокетов Беркли и, в конечном итоге, появления API сокетов POSIX, [2] некоторые функции были объявлены устаревшими или удалены и заменены другими. POSIX API также предназначен для повторного входа .
Действие | BSD | POSIX |
---|---|---|
Преобразование текстового адреса в упакованный адрес | inet_aton | inet_pton |
Преобразование упакованного адреса в текстовый адрес | inet_ntoa | inet_ntop |
Прямой поиск имени хоста / службы | gethostbyname, gethostbyaddr, getservbyname, getservbyport | getaddrinfo |
Обратный поиск имени хоста / службы | gethostbyaddr, getservbyport | getnameinfo |
Альтернативы
В РУЧЬЯХ основанного Transport Layer Интерфейс (ИТ) API предлагает альтернативу сокета API. Многие системы, которые предоставляют TLI API, также предоставляют API сокетов Berkeley.
Системы, отличные от Unix, часто предоставляют API сокетов Berkeley со слоем трансляции в собственный сетевой API. Plan 9 [3] и Genode [4] используют API файловой системы с управляющими файлами, а не с файловыми дескрипторами.
Заголовочные файлы
Интерфейс сокета Беркли определен в нескольких файлах заголовков. Имена и содержимое этих файлов немного различаются в зависимости от реализации. В общем, они включают:
Файл | Описание |
---|---|
sys / socket.h | Основные функции сокетов и структуры данных. |
нетинет / дюйм.ч | Семейства адресов AF_INET и AF_INET6 и соответствующие им семейства протоколов, PF_INET и PF_INET6. К ним относятся стандартные IP-адреса и номера портов TCP и UDP. |
sys / un.h | Семейство адресов PF_UNIX и PF_LOCAL. Используется для локальной связи между программами, работающими на одном компьютере. |
arpa / inet.h | Функции для управления числовыми IP-адресами. |
netdb.h | Функции для перевода имен протоколов и имен хостов в числовые адреса. Ищет локальные данные, а также службы имен. |
Функции Socket API
API сокетов Беркли обычно предоставляет следующие функции:
- socket () создает новый сокет определенного типа, идентифицируемого целым числом, и выделяет ему системные ресурсы.
- bind () обычно используется на стороне сервера и связывает сокет со структурой адреса сокета, то есть с указанным локальным IP-адресом и номером порта .
- listen () используется на стороне сервера и заставляет привязанный TCP-сокет перейти в состояние прослушивания.
- connect () используется на стороне клиента и присваивает сокету свободный номер локального порта. В случае TCP-сокета это вызывает попытку установить новое TCP-соединение.
- accept () используется на стороне сервера. Он принимает полученную входящую попытку создать новое TCP-соединение от удаленного клиента и создает новый сокет, связанный с парой адресов сокета этого соединения.
- send () , recv () , sendto () и recvfrom () используются для отправки и получения данных. Также могут использоваться стандартные функции write () и read () .
- close () заставляет систему освобождать ресурсы, выделенные сокету. В случае TCP соединение разрывается.
- gethostbyname () и gethostbyaddr () используются для разрешения имен и адресов хостов. Только IPv4.
- select () используется для приостановки, ожидания, пока один или несколько сокетов из предоставленного списка будут готовы к чтению, готовы к записи или имеют ошибки.
- poll () используется для проверки состояния сокета в наборе сокетов. Набор может быть протестирован, чтобы увидеть, можно ли в какой-либо сокет записывать, читать или возникла ли ошибка.
- getsockopt () используется для получения текущего значения конкретной опции сокета для указанного сокета.
- setsockopt () используется для установки конкретной опции сокета для указанного сокета.
разъем
Функция socket () создает конечную точку для связи и возвращает файловый дескриптор для сокета. Он использует три аргумента:
- домен , который определяет семейство протоколов созданного сокета. Например:
- AF_INET для сетевого протокола IPv4 (только IPv4)
- AF_INET6 для IPv6 (и в некоторых случаях обратно совместим с IPv4)
- AF_UNIX для локального сокета (с использованием специального узла файловой системы)
- тип , один из:
- SOCK_STREAM (надежный потоковый сервис или потоковые сокеты )
- SOCK_DGRAM (служба дейтаграмм или сокеты дейтаграмм )
- SOCK_SEQPACKET (надежный упорядоченный пакетный сервис)
- SOCK_RAW (необработанные протоколы на сетевом уровне)
- протокол, указывающий фактический используемый транспортный протокол. Наиболее распространеныIPPROTO_TCP ,IPPROTO_SCTP ,IPPROTO_UDP ,IPPROTO_DCCP . Эти протоколы определены в файле netinet / in.h . Значение 0 может использоваться для выбора протокола по умолчанию из выбранного домена и типа.
Функция возвращает -1, если произошла ошибка. В противном случае он возвращает целое число, представляющее вновь назначенный дескриптор.
связывать
bind () связывает сокет с адресом. Когда сокет создается с помощью socket () , ему предоставляется только семейство протоколов, но не назначается адрес. Это соединение должно быть выполнено до того, как сокет сможет принимать соединения от других хостов. У функции есть три аргумента:
- sockfd , дескриптор, представляющий сокет
- my_addr , указатель на структуру sockaddr, представляющую адрес для привязки.
- addrlen , поле типа socklen_t, определяющее размер структуры sockaddr .
bind () возвращает 0 в случае успеха и -1 в случае ошибки.
Слушать
После того, как сокет был связан с адресом, listen () подготавливает его для входящих соединений. Однако это необходимо только для потоковых (ориентированных на соединение) режимов данных, т. Е. Для типов сокетов ( SOCK_STREAM , SOCK_SEQPACKET ). listen () требует двух аргументов:
- sockfd , действительный дескриптор сокета.
- backlog - целое число, представляющее количество ожидающих соединений, которые могут быть поставлены в очередь в любой момент. Операционная система обычно ограничивает это значение.
Как только соединение принято, оно удаляется из очереди. В случае успеха возвращается 0. В случае ошибки возвращается -1.
принимать
Когда приложение прослушивает потоковые соединения от других хостов, оно уведомляется о таких событиях (см. Функцию select () ) и должно инициализировать соединение с помощью функции accept () . Он создает новый сокет для каждого соединения и удаляет соединение из очереди прослушивания. У функции есть следующие аргументы:
- sockfd , дескриптор прослушивающего сокета, который поставил соединение в очередь.
- cliaddr , указатель на структуру sockaddr для получения информации об адресе клиента.
- addrlen , указатель на местоположение socklen_t, который указывает размер структуры адреса клиента, переданной в accept (). Когда accept () возвращается, это место содержит размер (в байтах) структуры.
accept () возвращает новый дескриптор сокета для принятого соединения или значение -1 в случае возникновения ошибки. Все дальнейшие коммуникации с удаленным хостом теперь происходят через этот новый сокет.
Сокеты дейтаграмм не требуют обработки с помощью accept (), поскольку получатель может немедленно ответить на запрос, используя прослушивающий сокет.
соединять
connect () устанавливает прямую связь с конкретным удаленным хостом, идентифицируемым по его адресу, через сокет, идентифицируемый его файловым дескриптором.
При использовании протокола, ориентированного на установление соединения, устанавливается соединение. Некоторые типы протоколов не требуют установления соединения, в первую очередь протокол пользовательских дейтаграмм . При использовании с протоколами без установления соединения connect определяет удаленный адрес для отправки и получения данных, позволяя использовать такие функции, как send и recv . В этих случаях функция подключения предотвращает прием дейтаграмм из других источников.
connect () возвращает целое число, представляющее код ошибки: 0 означает успех, а –1 представляет ошибку. Исторически сложилось так, что в системах, производных от BSD, состояние дескриптора сокета не определено, если вызов для подключения терпит неудачу (как это указано в спецификации Single Unix), поэтому переносимые приложения должны немедленно закрыть дескриптор сокета и получить новый дескриптор с socket () в случае сбоя вызова connect (). [5]
gethostbyname и gethostbyaddr
Функции gethostbyname () и gethostbyaddr () используются для разрешения имен и адресов хостов в системе доменных имен или других механизмах преобразователя локального хоста (например, поиск / etc / hosts). Они возвращают указатель на объект типа struct hostent , который описывает хост интернет-протокола . Функции используют следующие аргументы:
- name указывает DNS-имя хоста.
- addr указывает указатель на структуру in_addr, содержащую адрес хоста.
- len указывает длину addr в байтах .
- type указывает тип семейства адресов (например, AF_INET) адреса хоста.
Функции возвращают указатель NULL в случае ошибки, и в этом случае внешнее целое число h_errno можно проверить, чтобы увидеть, является ли это временной ошибкой, недопустимым или неизвестным хостом. В противном случаевозвращаетсядействительная структура hostent * .
Эти функции не являются строго компонентом API сокетов BSD, но часто используются вместе с функциями API. Более того, эти функции теперь считаются устаревшими интерфейсами для запросов к системе доменных имен. Были определены новые функции, которые полностью не зависят от протокола (поддерживают IPv6). Эти новые функции - getaddrinfo () и getnameinfo () , основаны на новой структуре данных addrinfo .
Протоколы и адреса семей
API сокетов Berkeley - это общий интерфейс для сетевого и межпроцессного взаимодействия, который поддерживает использование различных сетевых протоколов и адресных архитектур.
Ниже приведены примеры семейств протоколов (которым предшествует стандартный символический идентификатор), определенных в современной реализации Linux или BSD :
Идентификатор | Функция или использование |
---|---|
PF_LOCAL, PF_UNIX, PF_FILE | Локальный для хоста (каналы и файл-домен) |
PF_INET | Интернет-протокол версии 4 |
PF_AX25 | Любительское радио AX.25 |
PF_IPX | Межсетевой обмен пакетами Novell |
PF_APPLETALK | AppleTalk |
PF_NETROM | Любительское радио NetROM (относится к AX.25) |
PF_BRIDGE | Многопротокольный мост |
PF_ATMPVC | Постоянные виртуальные цепи в асинхронном режиме передачи |
PF_ATMSVC | Коммутируемые виртуальные цепи с асинхронным режимом передачи |
PF_INET6 | Интернет-протокол версии 6 |
PF_DECnet | Зарезервировано для проекта DECnet |
PF_NETBEUI | Зарезервировано для проекта 802.2LLC |
PF_SECURITY | Обратный вызов безопасности псевдо AF |
PF_KEY | API управления ключами PF_KEY |
PF_NETLINK, PF_ROUTE | API маршрутизации |
PF_PACKET | Сокеты для захвата пакетов |
PF_ECONET | Желудь Эконет |
PF_SNA | Проект сетевой архитектуры систем Linux (SNA) |
PF_IRDA | IrDA розетки |
PF_PPPOX | PPP через X сокетов |
PF_WANPIPE | Сокеты Sangoma Wanpipe API |
PF_BLUETOOTH | Розетки Bluetooth |
Сокет для связи создается с помощью socket()
функции путем указания желаемого семейства протоколов ( PF_ -идентификатор ) в качестве аргумента.
Первоначальная концепция дизайна интерфейса сокета различала типы (семейства) протоколов и конкретные типы адресов, которые каждый из них может использовать. Предполагалось, что семейство протоколов может иметь несколько типов адресов. Типы адресов определялись дополнительными символическими константами с использованием префикса AF вместо ПФ . В Идентификаторы AF предназначены для всех структур данных, которые конкретно имеют дело с типом адреса, а не семейством протоколов. Однако эта концепция разделения протокола и типа адреса не нашла поддержки в реализации, и AF -константы определялись соответствующим идентификатором протокола, оставляя различие между AF и Константы PF как технический аргумент, не имеющий практического значения. Действительно, существует большая путаница в правильном использовании обеих форм. [6]
Спецификация POSIX.1-2008 не определяет никаких PF -константы, но только AF -константы [7]
Сырые сокеты
Необработанные сокеты предоставляют простой интерфейс, который обходит обработку стеком TCP / IP хоста. Они позволяют реализовать сетевые протоколы в пространстве пользователя и помогают в отладке стека протоколов. [8] Необработанные сокеты используются некоторыми службами, такими как ICMP , которые работают на Интернет-уровне модели TCP / IP.
Блокирующий и неблокирующий режим
Сокеты Berkeley могут работать в одном из двух режимов: блокирующем или неблокирующем.
Блокирующий сокет не возвращает управление, пока он не отправит (или не получит) некоторые или все данные, указанные для операции. Блокирующий сокет не отправляет все данные - это нормально. Приложение должно проверить возвращаемое значение, чтобы определить, сколько байтов было отправлено или получено, и оно должно повторно отправить любые данные, которые еще не обработаны. [9] При использовании блокирующих сокетов особое внимание следует уделить accept (), поскольку он все еще может блокироваться после индикации удобочитаемости, если клиент отключается во время фазы подключения.
Неблокирующий сокет возвращает все, что находится в приемном буфере, и немедленно продолжает работу. В случае неправильного написания программы, использующие неблокирующие сокеты, особенно подвержены гонкам из-за различий в скорости сетевого соединения. [ необходима цитата ]
Сокет обычно устанавливается в блокирующий или неблокирующий режим с помощью функций fcntl и ioctl .
Оконечные розетки
Операционная система не освобождает ресурсы, выделенные сокету, пока сокет не будет закрыт. Это особенно важно, если вызов подключения завершится неудачно и будет повторяться.
Когда приложение закрывает сокет, разрушается только интерфейс к сокету. Ядро несет ответственность за внутреннее уничтожение сокета. Иногда сокет может входить в Состояние TIME_WAIT на стороне сервера до 4 минут. [10]
В системах SVR4 использование close()
может привести к удалению данных. В shutdown()
этих системах может потребоваться использование или SO_LINGER, чтобы гарантировать доставку всех данных. [11]
Пример клиент-сервер с использованием TCP
Протокол управления передачей (TCP) представляет собой ориентированный на соединение протокол , который обеспечивает различные исправления ошибок и производительности функций для передачи потоков байтов. Процесс создает сокет TCP, вызывая socket()
функцию с параметрами для семейства протоколов ( PF INET , PF_INET6), режим сокета дляпотоковых сокетов( SOCK_STREAM ) и идентификатор протокола IP для TCP ( IPPROTO_TCP ).
Сервер
Установка TCP-сервера включает следующие основные шаги:
- Создание TCP-сокета с вызовом socket ().
- Привязка сокета к порту прослушивания ( bind () ) после установки номера порта.
- Подготовка сокета к прослушиванию соединений (превращение его в прослушивающий сокет) с помощью вызова listen () .
- Прием входящих подключений ( accept () ). Это блокирует процесс до тех пор, пока не будет получено входящее соединение, и вернет дескриптор сокета для принятого соединения. Первоначальный дескриптор остается дескриптором прослушивания, и accept () может быть вызван снова в любое время с этим сокетом, пока он не будет закрыт.
- Взаимодействие с удаленным хостом с помощью функций API send () и recv () , а также с помощью функций общего назначения write () и read () .
- Закрытие каждого сокета, который был открыт после использования, с помощью функции close ()
Следующая программа создает TCP-сервер, прослушивающий порт номер 1100:
#include # включить #include #include #include #include #include #include int main (пусто) { struct sockaddr_in sa; int SocketFD = сокет (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (SocketFD == -1) { perror («не могу создать сокет»); выход (EXIT_FAILURE); } memset (& sa, 0, sizeof sa); sa.sin_family = AF_INET; sa.sin_port = htons (1100); sa.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (SocketFD, (struct sockaddr *) & sa, sizeof sa) == -1) { perror («сбой привязки»); закрыть (SocketFD); выход (EXIT_FAILURE); } if (слушать (SocketFD, 10) == -1) { perror («прослушать не удалось»); закрыть (SocketFD); выход (EXIT_FAILURE); } для (;;) { int ConnectFD = accept (SocketFD, NULL, NULL); if (ConnectFD == -1) { perror ("принять не удалось"); закрыть (SocketFD); выход (EXIT_FAILURE); } / * выполняем операции чтения-записи ... читать (ConnectFD, бафф, размер) * / if (выключение (ConnectFD, SHUT_RDWR) == -1) { perror («сбой выключения»); закрыть (ConnectFD); закрыть (SocketFD); выход (EXIT_FAILURE); } закрыть (ConnectFD); } закрыть (SocketFD); вернуть EXIT_SUCCESS; }
Клиент
Программирование клиентского приложения TCP включает следующие шаги:
- Создание сокета TCP.
- Соединяясь с сервером ( connect () ), передавая
sockaddr_in
структуру сsin_family
установленным значением в AF_INET ,sin_port
устанавливается на порт, который конечная точка прослушивает (в сетевом порядке байтов), иsin_addr
устанавливается на IP-адрес прослушивающего сервера (также в сетевом порядке байтов). - Взаимодействие с удаленным хостом с помощью функций API send () и recv () , а также с помощью функций общего назначения write () и read () .
- Закрытие каждого сокета, открытого после использования, с помощью функции close ().
#include # включить #include #include #include #include #include #include int main (пусто) { struct sockaddr_in sa; int res; int SocketFD; SocketFD = сокет (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (SocketFD == -1) { perror («не могу создать сокет»); выход (EXIT_FAILURE); } memset (& sa, 0, sizeof sa); sa.sin_family = AF_INET; sa.sin_port = htons (1100); res = inet_pton (AF_INET, «192.168.1.3», & sa.sin_addr); if (connect (SocketFD, (struct sockaddr *) & sa, sizeof sa) == -1) { perror («сбой подключения»); закрыть (SocketFD); выход (EXIT_FAILURE); } / * выполняем операции чтения и записи ... * / закрыть (SocketFD); вернуть EXIT_SUCCESS; }
Пример клиент-сервер с использованием UDP
Протокол пользовательских дейтаграмм (UDP) - это протокол без установления соединения без гарантии доставки. Пакеты UDP могут приходить не по порядку, несколько раз или вообще не поступать. Из-за такой минималистичной конструкции у UDP значительно меньше накладных расходов, чем у TCP. Отсутствие соединения означает отсутствие концепции потока или постоянного соединения между двумя хостами. Такие данные называются дейтаграммами ( Datagram Sockets ).
Адресное пространство UDP, пространство номеров портов UDP (в терминологии ISO, TSAP ), полностью не пересекается с пространством портов TCP.
Сервер
Приложение может настроить UDP-сервер на порт номер 7654 следующим образом. Программа содержит бесконечный цикл, который принимает дейтаграммы UDP с помощью функции recvfrom () .
#include #include #include # включить #include #include #include / * для close () для сокета * / #include int main (пусто){ int sock; struct sockaddr_in sa; char buffer [1024]; ssize_t recsize; socklen_t fromlen; memset (& sa, 0, sizeof sa); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl (INADDR_ANY); sa.sin_port = htons (7654); fromlen = sizeof sa; sock = сокет (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (bind (sock, (struct sockaddr *) & sa, sizeof sa) == -1) { perror («ошибка привязки не удалась»); близко (носок); выход (EXIT_FAILURE); } для (;;) { recsize = recvfrom (sock, (void *) buffer, sizeof buffer, 0, (struct sockaddr *) & sa, & fromlen); if (recsize <0) { fprintf (stderr, "% s \ n", strerror (errno)); выход (EXIT_FAILURE); } printf ("recsize:% d \ n", (int) recsize); сон (1); printf ("дейтаграмма:%. * s \ n", (int) recsize, buffer); }}
Клиент
Ниже представлена клиентская программа для отправки UDP-пакета, содержащего строку «Hello World!». по адресу 127.0.0.1 на порт номер 7654.
#include #include #include #include # включить #include #include #include #include int main (пусто){ int sock; struct sockaddr_in sa; int bytes_sent; char buffer [200]; strcpy (буфер, «привет, мир!»); / * создаем Интернет, дейтаграмму, сокет с использованием UDP * / sock = сокет (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock == -1) { / * если сокет не удалось инициализировать, выходим * / printf («Ошибка создания сокета»); выход (EXIT_FAILURE); } / * Обнулить адрес сокета * / memset (& sa, 0, sizeof sa); / * Адрес IPv4 * / sa.sin_family = AF_INET; / * IPv4-адреса - это uint32_t, преобразовываем строковое представление октетов в соответствующее значение * / sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); / * сокеты - это беззнаковые шорты, htons (x) гарантирует, что x находится в сетевом порядке байтов, установите порт на 7654 * / sa.sin_port = htons (7654); bytes_sent = sendto (сок, буфер, strlen (буфер), 0, (struct sockaddr *) & sa, sizeof sa); if (bytes_sent <0) { printf ("Ошибка отправки пакета:% s \ n", strerror (errno)); выход (EXIT_FAILURE); } близко (носок); / * закрываем сокет * / возврат 0;}
В этом коде buffer является указателем на данные, которые должны быть отправлены, а buffer_length указывает размер данных.
Рекомендации
- ^ E. g. на языке программирования Ruby ruby-doc :: Socket
- ^ "- Спецификация POSIX.1-2008" . Opengroup.org . Проверено 26 июля 2012 .
- ^ «Организация сетей в плане 9» .
- ^ «Стек Linux TCP / IP как плагин VFS» .
- ^ 2013, Стивенс и Раго 607 .
- ^ UNIX Network Programming Volume 1, Third Edition: The Sockets Networking API, У. Ричард Стивенс, Билл Феннер, Эндрю М. Рудофф, Аддисон Уэсли, 2003.
- ^ "Базовые спецификации открытой группы, выпуск 7" . Pubs.opengroup.org . Проверено 26 июля 2012 .
- ^ https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548(v=vs.85).aspx
- ^ «Руководство Биджа по сетевому программированию» . Beej.us. 2007-05-05 . Проверено 26 июля 2012 .
- ^ "оконечные розетки" . Softlab.ntua.gr . Проверено 26 июля 2012 .
- ^ «ntua.gr - Программирование сокетов UNIX на языке C - Часто задаваемые вопросы: вопросы, касающиеся как клиентов, так и серверов (TCP / SOCK_STREAM)» . Softlab.ntua.gr . Проверено 26 июля 2012 .
Де - юре стандартное определение интерфейса Sockets содержится в стандарте POSIX, известный как:
- IEEE Std. 1003.1-2001 Стандарт информационных технологий - интерфейс переносимой операционной системы (POSIX).
- Технический стандарт Open Group: базовые спецификации, выпуск 6, декабрь 2001 г.
- ИСО / МЭК 9945: 2002
Информация об этом стандарте и текущей работе над ним доступна на веб-сайте Остина .
Расширения IPv6 для API базового сокета задокументированы в RFC 3493 и RFC 3542.
- У. Ричард, Стивенс; Стивен А., Раго (24 мая 2013 г.). Расширенное программирование в среде UNIX (Третье изд.). Эддисон-Уэсли Профессионал . ISBN 978-0321637734. Проверено 27 февраля 2015 года .
Внешние ссылки
- Дополнительные документы для программистов UNIX (PSD: 20-1)
- Руководство Биджа по сетевому программированию - 2007
- Перенос программ Berkeley Socket на Winsock - документация Microsoft.
- Программирование сокетов UNIX на C - Часто задаваемые вопросы - 1996
- Сетевое программирование Linux - Linux Journal , 1998
Эта статья основана на материалах, взятых из Free On-line Dictionary of Computing до 1 ноября 2008 г. и включенных в соответствии с условиями «перелицензирования» GFDL версии 1.3 или новее.