Provided by: manpages-ru_0.98-4_all bug

ИМЯ

       accept - принять соединение на сокете

ОБЗОР

       #include <sys/types.h>
       #include <sys/socket.h>

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

ОПИСАНИЕ

       Функция   accept   используется   с   сокетами,   ориентированными   на
       устанавление соединения (SOCK_STREAM, SOCK_SEQPACKET и SOCK_RDM).   Эта
       функция  извлекает  первый  запрос  на  соединение из очереди ожидающих
       соединений,  создаёт  новый  подключенный  сокет  почти  с  такими   же
       параметрами,   что  и  у  s,  и  выделяет  для  сокета  новый  файловый
       дескриптор, который и возвращается.  Новый сокет более не  находится  в
       слушающем  состоянии.   Исходный сокет s не изменяется при этом вызове.
       Заметим, что флаги файловых дескрипторов (те, что  можно  установить  с
       помощью   параметра   F_SETFL   функции  fcntl,  типа  неблокированного
       состояния или асинхронного ввода-вывода) не наследуются новым  файловым
       дескриптором после accept.

       Аргумент  s  --  это  сокет,  который  был  создан с помощью socket(2),
       привязан к локальному адресу с помощью bind(2),  и  слушает  соединения
       после listen(2).

       Аргумент  addr -- это указатель на структуру sockaddr.  В эту структуру
       помещается адрес другой стороны, в том виде, в  каком  он  известен  на
       коммуникационном   уровне.    Точный  формат  адреса,  передаваемого  в
       параметре addr, определяется  "семейством"  сокета  (см.   socket(2)  и
       страницу  руководства по соответствующему протоколу).  Аргумент addrlen
       является параметром, передаваемым по ссылке: перед вызовом он  содержит
       размер  структуры,  на  которую  ссылается  addr,  а  после  вызова  --
       действительную длину адреса в байтах.  Если  addr  равен  NULL,  он  не
       заполняется.

       Если  в  очереди  нет  запросов на соединение, и на сокет не установлен
       флаг,  что  он  является  неблокирующим,  accept  блокирует   вызвавшую
       программу  до появления соединения.  Если сокет является неблокирующим,
       а в очереди нет запросов на соединение, то accept возвращает EAGAIN.

       Для того, чтобы получать уведомления о входящих сооединениях на сокете,
       можно  использовать select(2) или poll(2).  В этом случае, когда придёт
       запрос на новое соединение, будет доставлено событие "можно читать",  и
       после  этого  вы  можете вызвать accept, чтобы получить сокет для этого
       соединения.  Можно также настроить сокет так, чтобы он  посылал  сигнал
       SIGIO,  когда  на нём происходит какая-либо активность; см.  socket(7),
       где описаны детали.

       Для определённых  протоколов,  которые  требуют  явного  подтверждения,
       например, DECNet, системный вызов accept можно рассматривать просто как
       извлечение  из   очереди   следующего   запроса   на   соединение,   не
       подразумевающее   подтверждение.    Подтверждение,   в   свою  очередь,
       произойдет  при  следующем  чтении  или   записи   в   новом   файловом
       дескрипторе, а отказ от соединения может произойти при закрытии сокета.
       В настоящий момент под Linux такую семантику имеет только DECNet.

ЗАМЕЧАНИЯ

       Не всегда после доставки сигнала SIGIO или после возврата из  select(2)
       или  poll(2)  в  очереди  будет  находиться соединение.  Оно могло быть
       удалено в той же нити из-за асинхронной сетевой ошибки или же в  другой
       нити  до  вызова  accept.  Если такое произойдет, то accept заблокирует
       выполнение до следующего соединения.  Чтобы убедиться,  что  такого  не
       произойдет  в  любом  случае,  на  сокет  s должен быть установлен флаг
       O_NONBLOCK (см.  socket(7)).

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

       Этот системный вызов возвращает  -1  в  случае  ошибки.   При  успешном
       завершении  возвращается неотрицательное целое, являющееся дескриптором
       сокета.

ОБРАБОТКА ОШИБОК

       accept в реализации Linux передаёт  уже  ожидающие  сетевые  ошибки  на
       новый сокет, как код ошибки из вызова accept.  Это поведение отличается
       от других  реализаций  BSD-сокетов.   Для  надёжной  работы  приложения
       должны отслеживать сетевые ошибки, которые могут появиться при работе с
       протоколом, и обрабатывать их как  EAGAIN,  повторным  выполнением.   В
       случае  TCP/IP  такими ошибками являются ENETDOWN, EPROTO, ENOPROTOOPT,
       EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, и ENETUNREACH.

ОШИБКИ

       accept завершится с ошибкой если:

       EAGAIN или EWOULDBLOCK
              сокет маркирован как неблокирующий, но нет ни одного соединения,
              которое можно было бы принять.

       EBADF  Дескриптор неправилен.

       ENOTSOCK
              Дескриптор ссылается на файл, а не на сокет.

       EOPNOTSUPP
              Тип  сокета,  на  который  ссылается  дескриптор,  отличается от
              SOCK_STREAM.

       EINTR  Системный вызов был прерван сигналом, который был получен  перед
              тем как из очереди поступило корректное соединение.

       ECONNABORTED
              Соединение было прервано.

       EINVAL Сокет не слушает соединения.

       EMFILE Было достигнуто ограничение по открытым файловым дескриптором на
              процесс.

       ENFILE Был достигнут системный максимум на файловые дескрипторы.

       accept может завершиться с ошибкой если:

       Параметр
              EFAULT addr не находится в пространстве адресов  с  возможностью
              записи.

       ENOBUFS, ENOMEM
              Не   хватает  свободной  памяти.   Это  зачастую  означает,  что
              выделение памяти  ограничено  размерами  буфера  сокетов,  а  не
              системной памятью, но это не 100% верно.

       EPROTO Ошибка протокола.

       В Linux accept может завешиться с ошибкой если:

       EPERM  Правила межсетевого экрана запрещают соединение.

       Вдобавок,  могут  также  возвращаться  сетевые ошибки на новом сокете и
       ошибки, могущие возникнуть в протоколе.   Различные  ядра  Linux  могут
       вернуть другие ошибки, например, EMFILE, EINVAL, ENOSR, ENOBUFS, EPERM,
       ECONNABORTED, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT, ERESTARTSYS.

СООТВЕТСТВИЕ СТАНДАРТАМ

       SVr4,  4.4BSD  (функция  accept впервые появилась в BSD 4.2).  Страница
       руководства BSD  документирует  пять  возможных  кодов  ошибок  (EBADF,
       ENOTSOCK, EOPNOTSUPP, EWOULDBLOCK, EFAULT).  SUSv3 документирует ошибки
       EAGAIN, EBADF, ECONNABORTED, EINTR, EINVAL,  EMFILE,  ENFILE,  ENOBUFS,
       ENOMEM,  ENOTSOCK, EOPNOTSUPP, EPROTO, EWOULDBLOCK. В дополнение, SUSv2
       документирует EFAULT и ENOSR.

       Реализация  accept  в  Linux  _не_  наследует   флаги   сокетов   (типа
       O_NONBLOCK).    Это   поведение   отличается   от   других   реализаций
       BSD-сокетов.  Переносимые  программы  не  должны  полагаться  на  такое
       поведение  и  всегда  должны  устанавливать  на  сокете,  полученном от
       accept, все требуемые флаги.

ЗАМЕЧАНИЕ

       Третий аргумент функции accept изначально был объявлен как int  *  (это
       именно так в libc4, libc5 и на многих других системах, включая BSD 4.*,
       SunOS 4 и SGI); черновик стандарта POSIX 1003.1g пытался поменять  этот
       тип  на  size_t *, и в SunOS 5 это именно так.  Поздние черновики POSIX
       содержат socklen_t *, и в Single Unix Specification и glibc2 это именно
       так.

       По словам Линуса Торвальдса:

         __        "socklen_t"    int __
       .       BSD-.  
       POSIX   size_t,   (,  , - , 
           )      .     
         ,   ,  size_t     
       ,      "int",  ,    64-  .    
        ,   BSD- ,   .

           ,     POSIX     "socklen_t".
       ,          ,  
       -   ,    
        (,        ,    ,
           ,   ).

СМОТРИ ТАКЖЕ

       bind(2), connect(2), listen(2), select(2), socket(2)

ПЕРЕВОД

       Copyright  (C)  Alexey  Mahotkin  <alexm@hsys.msk.ru> 1999-2001, Виктор
       Вислобоков <corochoone@perm.ru> 2003