Вход/Регистрация
Разработка приложений в среде Linux. Второе издание
вернуться

Троан Эрик В.

Шрифт:

Как правило, функция

accept
блокируется до тех пор, пока к ней не пытается присоединиться некоторый клиентский процесс. Если сокет был помечен как неблокируемый через
fcntl
, то функция
accept
возвращает значение
EAGAIN
в том случае, если нет ни одного доступного клиентского процесса [120] . Системные вызовы
select
,
poll
и
epoll
могут использоваться для указания, ждать ли соединению обработки (эти вызовы помечают сокет как готовый для считывания) [121] .

120

Системный вызов

connect
может также быть неблокируемым, что позволит пользователям гораздо быстрее открывать несколько TCP соединений (он позволяет продолжать работу программы, в то время как выполняется процесс синхронизации TCP). Подробности по этой теме можно найти в [33].

121

Различные формы

select
помечают сокет как открытый для чтения, тогда как
accept
не может блокировать его, даже если сокет не помечен как неблокируемый. Для обеспечения максимальной переносимости функцию
select
необходимо применять только для принятия соглашений с неблокируемыми сокетами, хотя в системе Linux это фактически не нужно. Причины этого подробно рассматриваются в [33].

Ниже показаны прототипы

listen
и
accept
.

#include <sys/socket.h>

int listen(int sock, int backlog);

int accept(int sock, struct sockaddr * addr, socklen_t * addrlen);

В обеих функциях предполагается, что первый параметр — это файловый дескриптор. Второй параметр

backlog
функции
listen
задает максимальное количество соединений, которые могут одновременно ожидать обработки на данном сокете. Сетевые соединения не устанавливаются до тех пор, пока сервер не примет соединение через
accept
; все входящие соединения считаются приостановленными. Поддерживая небольшое количество ожидающих соединений в очереди, ядро тем самым освобождает серверные процессы от необходимости быть в постоянной готовности принимать соединения. Исторически принято ограничивать в приложениях количество невыполненных заданий пятью, хотя иногда необходимо большее количество. Функция
listen
возвращает ноль в случае успеха и какое-то другое число в случае неудачи.

Вызов

accept
превращает отложенное соединение в установленное. Установленное соединение получает новый файловый дескриптор, который возвращает функция
accept
. Новый дескриптор наследует все атрибуты того сокета, к которому обращалась функция
listen
. Необычное свойство
accept
состоит в том, что она возвращает сетевые ошибки, ожидающие обработки, как ошибки принятия от
accept
[122] . При возврате ошибки серверы не должны прерывать работу, если параметр
errno
принимает одно из следующих значений:
ECONNABORTED
,
ENETDOWN
,
EPROTO
,
ENOPROTOOPT
,
EHOSTDOWN
,
ENONET
,
EHOSTUNREACH
,
EOPNOTSUPP
или
ENETUNREACH
. Все эти ошибки необходимо игнорировать, просто вызвав функцию
accept
на сервере еще раз.

122

Варианты BSD не поддерживают такую модель поведения, в таких системах ошибки проходят без отчетов.

Параметры

addr
и
addrlen
указывают данные, в которых ядро размещает адрес удаленного (клиентского) конца соединения. В исходном состоянии
addrlen
представляет собой целое число, содержащее размер буфера, на который ссылается
addr
. Функция
accept
аналогично open возвращает файловый дескриптор или некоторое отрицательное значение, если возникла ошибка.

17.3.5. Подключение к серверу

Как и серверы, клиенты могут сразу после создания сокета связывать с ним локальный адрес. Обычно клиент пропускает этот шаг, предоставляя ядру присвоить сокету любой подходящий локальный адрес.

После этапа связывания (который, впрочем, может быть пропущен) клиент соединяется с сервером через системный вызов

connect
.

#include <sys/socket.h>

int connect(int sock, struct sockaddr * servaddr, socklen_t addrlen);

Процесс переходит к подключению, придерживаясь адреса, с которым должен соединиться сокет.

На рис. 17.1 показаны системные вызовы, которые обычно используются для установки соединений сокетов, и порядок, в котором они выполняются.

Рис 17.1. Установка соединений сокетов

17.3.6. Поиск адресов соединения

После того как соединение установлено, приложение может найти адреса как удаленного, так и локального концов сокета с помощью функций

getpeername
и
getsockname
.

#include <sys/socket.h>

int getpeername(int s, struct sockaddr * addr, socklen_t * addrlen);

int getsockname(int s, struct sockaddr * addr, socklen_t * addrlen);

Обе функции передают адреса соединений сокета s в те структуры, на которые указывают их параметры

addr
. Адрес удаленной стороны возвращается функцией
getpeername
, тогда как
getsockname
сообщает адрес локальной части соединения. Для обеих функций в качестве первоначального целочисленного значения, на которое указывает параметр
addrlen
, должен быть установлен размер пространства, которое выделяется параметром
addr
. Это целое число заменяется количеством байт в возвращаемом адресе.

17.4. Сокеты домена Unix

Сокеты домена Unix — это простейшее семейство протоколов, доступное через API- интерфейс сокетов. Они фактически не являются сетевыми протоколами, поскольку могут соединяться с сокетами только на одном и том же компьютере. Несмотря на то что это значительно ограничивает их полезность, они все же используются многими приложениями благодаря гибкому механизму IPC, который они поддерживают. Их адреса — это путевые имена, которые создаются в файловой системе, когда сокет привязывается к путевому имени. Файлы сокетов, представляющие адреса доменов Unix, могут быть запущены функцией

stat
, но не могут быть открыты с помощью
open
; вместо этого нужно использовать API сокетов.

  • Читать дальше
  • 1
  • ...
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: