Provided by: manpages-ru_4.19.0-7_all bug

ИМЯ

       unix - сокеты для локального межпроцессного взаимодействия

СИНТАКСИС

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

       unix_socket = socket(AF_UNIX, type, 0);
       error = socketpair(AF_UNIX, type, 0, int *sv);

ОПИСАНИЕ

       Семейство  сокетов  AF_UNIX  (также известное, как AF_LOCAL) используется для эффективного
       взаимодействия между процессами на одной машине.  Доменные  сокеты  UNIX  могут  быть  как
       безымянными,  так  и  иметь  имя  файла в файловой системе (типизированный сокет). В Linux
       также поддерживается  абстрактное  пространство  имён,  которое  не  зависит  от  файловой
       системы.

       Допустимые  типы  сокета  для  домена UNIX: потоковый сокет SOCK_STREAM, датаграмный сокет
       SOCK_DGRAM,  сохраняющий  границы  сообщений  (в  большинстве  реализаций  UNIX,  доменные
       датаграмные  сокеты UNIX всегда надёжны и не меняют порядок датаграмм); и (начиная с Linux
       2.6.4)   ориентированный  на  соединение   задающий   последовательность   пакетам   сокет
       SOCK_SEQPACKET, сохраняющий границы сообщений и доставляющий сообщения в том же порядке, в
       каком они были отправлены.

       Доменные сокеты UNIX  поддерживают  передачу  файловых  дескрипторов  или  учётных  данных
       (credentials) о процессе другим процессам, используя вспомогательные (ancillary) данные.

   Формат адреса
       Адрес доменного сокета UNIX представляет собой следующую структуру:

           struct sockaddr_un {
               sa_family_t sun_family;               /* AF_UNIX */
               char        sun_path[108];            /* имя пути */
           };

       The  sun_family  field  always contains AF_UNIX.  On Linux, sun_path is 108 bytes in size;
       see also BUGS, below.

       В различных системных вызовах (например,  bind(2),  connect(2)  и  sendto(2))  в  качестве
       входных  данных  используется  параметр  sockaddr_un.  Другие  системные вызовы (например,
       getsockname(2), getpeername(2), recvfrom(2) и accept(2)) возвращают результат в  параметре
       этого типа.

       В sockaddr_un структуре различают три типа адресов:

       pathname
              a  UNIX  domain  socket can be bound to a null-terminated filesystem pathname using
              bind(2).  When the address of a pathname socket is returned (by one of  the  system
              calls noted above), its length is

                  offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1

              и  sun_path  содержит  путь, оканчивающийся null (в Linux, указанное выше выражение
              offsetof() равно sizeof(sa_family_t), но в некоторых реализациях включаются  другие
              поля  перед  sun_path,  поэтому  выражение  offsetof()  описывает  размер  адресной
              структуры более переносимым способом).

              Дополнительную информацию о путях сокета смотрите далее.

       unnamed
              A stream socket that has not been bound to a pathname using bind(2)  has  no  name.
              Likewise,  the two sockets created by socketpair(2)  are unnamed.  When the address
              of an unnamed socket is returned, its length is sizeof(sa_family_t),  and  sun_path
              should not be inspected.

       abstract
              an  abstract  socket address is distinguished (from a pathname socket)  by the fact
              that sun_path[0] is a null byte ('\0').  The socket's address in this namespace  is
              given  by the additional bytes in sun_path that are covered by the specified length
              of the address structure.  (Null bytes in the name have no  special  significance.)
              The  name  has  no  connection  with  filesystem pathnames.  When the address of an
              abstract   socket   is   returned,   the   returned   addrlen   is   greater   than
              sizeof(sa_family_t) (i.e., greater than 2), and the name of the socket is contained
              in the first (addrlen - sizeof(sa_family_t)) bytes of sun_path.

   Путевые сокеты
       При привязке сокета к пути для максимальной переносимости  и  простоте  кодирования  нужно
       учесть несколько правил:

       •  Имя пути в sun_path должно завершаться null.

       •  Длина имени пути, включая завершающий байт null, не должна превышать размер sun_path.

       •  Аргумент  addrlen,  описывающий  включаемую  структуру  sockaddr_un,  должен  содержать
          значение, как минимум:

              offsetof(struct sockaddr_un, sun_path)+strlen(addr.sun_path)+1

          или, проще говоря, для addrlen можно использовать sizeof(struct sockaddr_un).

       Есть несколько реализаций по работе с адресами доменных сокетов UNIX, которые  не  следуют
       данным  правилам.  Например,  в некоторых реализациях (но не во всех) добавляется конечный
       null, если если его нет в sun_path.

       При  написании  переносимых  приложений  учтите,  что  в  некоторых   реализациях   размер
       sun_pathравен 92 байтам.

       Различные    системные   вызовы   (например,   accept(2),   recvfrom(2),   getsockname(2),
       getpeername(2)) возвращают адресные структуры сокета. В случае с доменными  сокетами  UNIX
       аргумент  значение-результат addrlen, передаваемый вызову, должен быть инициализирован как
       описано выше. При возврате в аргументе  содержится  реальный  размер  адресной  структуры.
       Вызывающий  должен  проверить  полученное  значение  этого  аргумента:  если оно превышает
       значение до вызова, то не  гарантируется  наличие  конечного  null  в  sun_path  (смотрите
       ДЕФЕКТЫ).

   Пути к сокетам и права
       В реализации Linux учитываются права на каталоги, в которых располагаются сокеты. Создание
       нового сокета  завершается  ошибкой,  если  процесс  не  имеет  права  писать  или  искать
       (выполнять) в каталог, в котором создаётся сокет.

       В  Linux  для  подключения  к  объекту  потокового сокета требуются права на запись в этот
       сокет; схожим образом, для отправки дейтаграммы в дейтаграммный сокет требуются  права  на
       запись  в  этот сокет. В POSIX ничего не сказано о влиянии прав файла сокета и в некоторых
       системах (например, в старых BSD) права на сокет игнорируются.  Переносимые  программы  не
       должны полагаться на это свойство для обеспечения безопасности.

       При  создании  нового  сокета  владелец и группа файла сокета назначаются согласно обычных
       правил. К файлу сокета разрешается любой доступ кроме  выключенного  процессом  с  помощью
       umask(2).

       Владелец,  группа  и  права  доступа  пути  сокета  можно  изменять  (с помощью chown(2) и
       chmod(2)).

   Абстрактные сокеты
       Права на сокеты не учитываются у абстрактных сокетов: umask(2) процесса не учитывается при
       подключении  к  абстрактному  сокету  как  и  изменение владельца и прав доступа к объекту
       (посредством fchown(2) и fchmod(2)) не влияют на доступность сокета.

       Абстрактные сокеты автоматически исчезают при закрытии всех открытых ссылок на них.

       Пространство имён абстрактных сокетов является непереносимым расширением Linux.

   Параметры сокета
       В силу исторических причин эти параметры сокетов относятся к типу  SOL_SOCKET,  даже  если
       они  относятся к AF_UNIX. Они могут быть установлены с помощью setsockopt(2) и прочитаны с
       помощью getsockopt(2); тип SOL_SOCKET указывается в качестве семейства сокета.

       SO_PASSCRED
              Разрешает приём учётных данных посылающего  процесса  в  вспомогательном  сообщении
              SCM_CREDENTIALS каждого последующего принятого сообщения. Полученные учётные данные
              были  заданы  отправителем  с  помощью  SCM_CREDENTIALS,  или  имеют  значение   по
              умолчанию,   которое  содержит  PID  отправителя,  фактический  пользовательский  и
              групповой ID, если отправитель не задал вспомогательные данные SCM_CREDENTIALS.

              Если при включении  этого  параметра  сокет  ещё  не  соединён,  то  в  абстрактном
              пространстве имён будет автоматически создано уникальное имя.

              Значение   передаётся   в  аргументе  setsockopt(2)  и  возвращается  в  результате
              getsockopt(2) в виде целочисленного логического флага.

       SO_PASSSEC
              Разрешает приём метки безопасности SELinux однорангового сокета  в  вспомогательном
              сообщении с типом SCM_SECURITY (смотрите ниже).

              Значение   передаётся   в  аргументе  setsockopt(2)  и  возвращается  в  результате
              getsockopt(2) в виде целочисленного логического флага.

              Параметр SO_PASSSEC поддерживается для дейтаграммных доменных сокетов UNIX  начиная
              с Linux 2.6.18; поддержка потоковых доменных сокетов UNIX добавлена в Linux 4.2.

       SO_PEEK_OFF
              Смотрите socket(7).

       SO_PEERCRED
              С  параметром  сокета,  доступным  только  для  чтения, возвращаются учётные данные
              однорангового процесса, соединённого с сокетом. Возвращаются информационные данные,
              которые были действительными на момент вызова connect(2) или socketpair(2).

              Аргументом  getsockopt(2)  является указатель на структуру ucred; определите макрос
              тестирования свойств  _GNU_SOURCE  для  получения  определения  этой  структуры  из
              <sys/socket.h>.

              Использование  этого  параметра  возможо  только  для соединённых потоковых сокетов
              AF_UNIX и потоков AF_UNIX и для дейтаграммных сокетных  пар,  созданных  с  помощью
              socketpair(2).

       SO_PEERSEC
              This  read-only  socket  option  returns  the  security  context of the peer socket
              connected to this socket.  By default, this  will  be  the  same  as  the  security
              context of the process that created the peer socket unless overridden by the policy
              or by a process with the required permissions.

              The argument to getsockopt(2)  is a pointer to a buffer of the specified length  in
              bytes  into which the security context string will be copied.  If the buffer length
              is less than the length of the security context string, then getsockopt(2)  returns
              -1,  sets  errno to ERANGE, and returns the required length via optlen.  The caller
              should allocate at least NAME_MAX bytes for the buffer initially, although this  is
              not  guaranteed  to  be sufficient.  Resizing the buffer to the returned length and
              retrying may be necessary.

              The security context string  may  include  a  terminating  null  character  in  the
              returned  length, but is not guaranteed to do so: a security context "foo" might be
              represented as either {'f','o','o'} of length 3 or {'f','o','o','\0'} of length  4,
              which  are  considered  to  be  interchangeable.  The string is printable, does not
              contain non-terminating null characters, and is  in  an  unspecified  encoding  (in
              particular, it is not guaranteed to be ASCII or UTF-8).

              The use of this option for sockets in the AF_UNIX address family is supported since
              Linux 2.6.2 for connected stream sockets, and since Linux 4.18 also for stream  and
              datagram socket pairs created using socketpair(2).

   Свойство автоматической привязки
       If  a  bind(2)   call  specifies addrlen as sizeof(sa_family_t), or the SO_PASSCRED socket
       option was specified for a socket that was not explicitly bound to an  address,  then  the
       socket  is autobound to an abstract address.  The address consists of a null byte followed
       by 5 bytes in the character set [0-9a-f].   Thus,  there  is  a  limit  of  2^20  autobind
       addresses.   (From  Linux  2.1.15, when the autobind feature was added, 8 bytes were used,
       and the limit was thus 2^32 autobind addresses.  The change  to  5  bytes  came  in  Linux
       2.3.15.)

   Программный интерфейс сокетов
       В  следующих  параграфах  описываются  специфичные  тонкости  доменов  и  неподдерживаемые
       возможности программного интерфейса сокетов для доменных сокетов UNIX в Linux.

       Доменные сокеты UNIX не поддерживают передачу внеполосных данных (флаг MSG_OOB у send(2) и
       recv(2)).

       Флаг MSG_MORE у send(2) не поддерживается доменными сокетами UNIX.

       До  Linux  3.4  использование  MSG_TRUNC  в  аргументе  flags  у recv(2) не поддерживалось
       доменными сокетами UNIX.

       Параметр сокета SO_SNDBUF учитывается в доменных сокетах UNIX, а параметр SO_RCVBUF — нет.
       Для  датаграмных  сокетов значение SO_SNDBUF считается максимальным размером для исходящих
       датаграмм. Это ограничение, вычисляемое как удвоенное значение (см. socket(7))  параметра,
       содержит меньше 32 байт накладных расходов.

   Вспомогательные сообщения
       Вспомогательные  данные  отправляются  и  принимаются с помощью sendmsg(2) и recvmsg(2). В
       силу исторических причин перечисленные типы вспомогательных  сообщений  относятся  к  типу
       SOL_SOCKET,  даже  если  они относятся к AF_UNIX. Для того, чтобы отправить их, установите
       значение поля cmsg_level структуры cmsghdr равным SOL_SOCKET, а в значении поля  cmsg_type
       укажите его тип. Дополнительная информация приведена в cmsg(3).

       SCM_RIGHTS
              Передать  или  принять  набор  открытых  файловых дескрипторов из другого процесса.
              Часть с данными содержит целочисленный массив файловых дескрипторов.

              Обычно, эта операция упоминается как «передача дескриптора файла» другому процессу.
              Но  если  точнее,  то  передается  ссылка  на  открытое файловое описание (смотрите
              open(2))  и  в  принимающем  процессе  будет  использоваться,  вероятно,   файловый
              дескриптор  с  другим номером. Семантически, эта операция эквивалентна дублированию
              (dup(2)) файлового дескриптора в таблицу файловых дескрипторов другого процесса.

              Если используемый для приёма вспомогательных данных с файловыми дескрипторами буфер
              слишком   мал   (или   отсутствует),  то  вспомогательные  данные  обрезаются  (или
              отбрасываются), а  избыточные  файловые  дескрипторы  автоматически  закрываются  в
              принимающем процессе.

              Если  количество  файловых  дескрипторов,  полученных  во  вспомогательных  данных,
              превышает ограничение ресурса процесса RLIMIT_NOFILE  (смотрите  getrlimit(2)),  то
              превысившие файловые дескрипторы автоматически закрываются в принимающем процессе.

              The kernel constant SCM_MAX_FD defines a limit on the number of file descriptors in
              the array.  Attempting to send an array larger than this  limit  causes  sendmsg(2)
              to  fail  with the error EINVAL.  SCM_MAX_FD has the value 253 (or 255 before Linux
              2.6.38).

       SCM_CREDENTIALS
              Send or receive UNIX credentials.   This  can  be  used  for  authentication.   The
              credentials  are  passed  as  a  struct ucred ancillary message.  This structure is
              defined in <sys/socket.h> as follows:

                  struct ucred {
                      pid_t pid;    /* идентификатор посылающего процесса */
                      uid_t uid;    /* идентификатор пользователя посылающего процесса */
                      gid_t gid;    /* идентификатор группы посылающего процесса */
                  };

              Начиная с glibc 2.8,  чтобы  получить  определение  данной  структуры  должен  быть
              определён   макрос   тестирования  свойств  _GNU_SOURCE  (до  включения  каких-либо
              заголовочных файлов).

              The credentials which the sender specifies are checked by the kernel.  A privileged
              process  is  allowed  to specify values that do not match its own.  The sender must
              specify its own process ID (unless it has the capability  CAP_SYS_ADMIN,  in  which
              case the PID of any existing process may be specified), its real user ID, effective
              user ID, or saved set-user-ID (unless it has CAP_SETUID), and its  real  group  ID,
              effective group ID, or saved set-group-ID (unless it has CAP_SETGID).

              Для  получения  сообщения  со  структурой struct ucred у сокета должен быть включён
              параметр SO_PASSCRED.

       SCM_SECURITY
              Получить контекст безопасности SELinux (метку безопасности)  однорангового  сокета.
              Полученные  вспомогательные  данные  представляют  собой  строку (с null в конце) с
              контекстом безопасности. Получатель должен выделить не менее NAME_MAX байт под  эти
              данные в в части данных вспомогательного сообщения.

              Для  получения  контекста  безопасности  у  сокета  должен  быть  включён  параметр
              SO_PASSSEC (смотрите выше).

       При отправке вспомогательных  данных  с  помощью  sendmsg(2)  посылаемое  сообщение  может
       содержать только по одному элементу каждого типа, из представленных выше.

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

       При получении из потокового сокета вспомогательные данные формируют своего рода барьер для
       полученных данных. Например, предположим, что отправитель передает так:

              (1)  sendmsg(2) отправляет четыре байта без вспомогательных данных.
              (2)  sendmsg(2) отправляет один байт вспомогательных данных.
              (3)  sendmsg(2) отправляет четыре байта без вспомогательных данных.

       Suppose that the receiver now performs recvmsg(2)  calls each with a  buffer  size  of  20
       bytes.  The first call will receive five bytes of data, along with the ancillary data sent
       by the second sendmsg(2)  call.  The next call will receive the remaining  four  bytes  of
       data.

       Если  место,  выделенное для получения входящих вспомогательных данных, слишком маленькое,
       то  вспомогательные  данные  обрезаются  по  количеству  заголовков,  которые   влезут   в
       предоставленной  буфер  (или, в случае списка файловых дескрипторов SCM_RIGHTS, может быть
       обрезан список файловых дескрипторов). Если для входящих вспомогательных данных  буфер  не
       был предусмотрен (т. е., поле msg_control в структуре msghdr, указанное recvmsg(2),  равно
       NULL), то входящие вспомогательные данные отбрасываются. В обоих случаях,  в  возвращаемом
       значении recvmsg(2) в msg.msg_flags будет установлен флаг MSG_CTRUNC.

   Вызовы ioctl
       Следующие вызовы ioctl(2) возвращают информацию в аргументе value. Корректный синтаксис:

              int value;
              error = ioctl(unix_socket, ioctl_type, &value);

       Значением ioctl_type может быть:

       SIOCINQ
              Для  сокетов  SOCK_STREAM  этот  вызов возвращает количество непрочитанных данных в
              приёмном буфере. Сокет не должен быть в состоянии LISTEN, иначе возвращается ошибка
              (EINVAL).  Значение SIOCINQ определено в <linux/sockios.h>. В качестве альтернативы
              можно использовать синоним FIONREAD,  определённый  в  <sys/ioctl.h>.  Для  сокетов
              SOCK_DGRAM  возвращаемое  значение  совпадает  с  дейтаграммными доменными сокетами
              Интернета; смотрите udp(7).

ОШИБКИ

       EADDRINUSE
              Заданный локальный адрес уже используется, или сокетный объект файловой системы уже
              существует.

       EBADF  Эта  ошибка  может  возникать  в  sendmsg(2)  при  отправке файлового дескриптора в
              вспомогательных данных через доменный  сокет  UNIX  (смотрите  описание  SCM_RIGHTS
              выше),  и указывает на то, что отправляемый номер файлового дескриптора некорректен
              (например, не является открытым файловым дескриптором).

       ECONNREFUSED
              Удалённый адрес, указанный connect(2) не является  слушающим  сокетом.  Эта  ошибка
              также может возникнуть, если путь назначения не является сокетом.

       ECONNRESET
              Удалённый сокет был неожиданно закрыт.

       EFAULT Некорректный адрес пользовательской памяти.

       EINVAL Передан неправильный аргумент. Основная причина — не задано значение AF_UNIX в поле
              sun_type передаваемых адресов или сокет  находится  в  некорректном  состоянии  для
              производимой операции.

       EISCONN
              Вызов  connect(2)  запущен  для  уже  соединённого  сокета,  или  адрес  назначения
              указывает на соединённый сокет.

       ENFILE Достигнуто максимальное количество открытых файлов в системе.

       ENOENT Путь, указанный в удалённом адресе для connect(2), не существует.

       ENOMEM Не хватает памяти.

       ENOTCONN
              Для операции над сокетом требуется адрес назначения, а сокет не соединён.

       EOPNOTSUPP
              Вызвана потоковая операция  для  не  потокового  сокета,  или  произведена  попытка
              использования параметра для внеполосных данных.

       EPERM  Отправитель указал неправильную информацию (credentials) в структуре struct ucred.

       EPIPE  Удалённый  сокет  был закрыт в потоковом сокете. Если разрешено, также будет послан
              сигнал SIGPIPE. Этого можно избежать, передав флаг MSG_NOSIGNAL при вызове  send(2)
              или sendmsg(2).

       EPROTONOSUPPORT
              Указанный протокол не является AF_UNIX.

       EPROTOTYPE
              Удалённый   сокет  не  совпадает  с  типом  локального  сокета  (SOCK_DGRAM  против
              SOCK_STREAM).

       ESOCKTNOSUPPORT
              Неизвестный тип сокета.

       ESRCH  While sending an ancillary message containing  credentials  (SCM_CREDENTIALS),  the
              caller specified a PID that does not match any existing process.

       ETOOMANYREFS
              Эта  ошибка  может возникнуть в sendmsg(2) при передаче через доменный сокет UNIX в
              качестве вспомогательных данных файлового дескриптора (смотрите описание SCM_RIGHTS
              выше).  Это  происходит, если количество файловых дескрипторов «в полёте» превышает
              ограничитель ресурса RLIMIT_NOFILE и вызывающий не имеет мандата  CAP_SYS_RESOURCE.
              Файловым  дескриптором в полёте считается посланный с помощью sendmsg(2), но ещё не
              принятый процессом-получателем с помощью recvmsg(2).

              Данная ошибка выявляется начиная с Linux 4.5  (и  в  некоторых  старых  версиях,  в
              которые  перенесено  исправление).  В  ранних  версиях  ядра было возможно получить
              неограниченное количество файловых дескрипторов в полёте, посылая  каждый  файловый
              дескриптор  с  помощью  sendmsg(2)  и  затем  закрывая файловый дескриптор, и таким
              образом он не учитывался в ограничителе ресурса RLIMIT_NOFILE.

       При создании сокетного объекта на уровне сокетов или файловой системы могут генерироваться
       другие  ошибки.  За  дополнительной  информацией  обращайтесь к соответствующей справочной
       странице.

ВЕРСИИ

       SCM_CREDENTIALS и абстрактное  пространство  имён  появились  в  Linux  2.2  и  не  должны
       использоваться  в  переносимых программах. Некоторые клоны BSD также поддерживают передачу
       дополнительной информации (credential),  но  методы  реализации  передачи  могут  серьезно
       отличаться на разных системах.

ЗАМЕЧАНИЯ

       Привязка сокета к имени файла создаёт сокет в файловой системе, который должен быть удалён
       создателем, когда необходимость в нём  отпадёт  (с  помощью  unlink(2)).  Обычная  система
       ссылок UNIX также подходит для работы с сокетами; сокет может быть удалён в любое время, а
       реальное удаление из файловой системы будет произведено при  закрытии  последней  на  него
       ссылки.

       To  pass  file  descriptors  or  credentials  over  a SOCK_STREAM socket, you must send or
       receive at least one byte of nonancillary data  in  the  same  sendmsg(2)   or  recvmsg(2)
       call.

       В потоковых доменных сокетах UNIX отсутствует такое понятие как внеполосные данные.

ДЕФЕКТЫ

       При  привязке  сокета  к  адресу  Linux  является  одной  из реализаций, которые добавляют
       конечный null, если он отсутствует в sun_path. В большинстве случаев в этом нет  проблемы:
       когда  адрес  сокета  возвращается,  он будет на один байт длиннее чем был перед привязкой
       сокета. Однако такое неожиданное поведение может привести к  следующему:  если  передаётся
       108  не-null байтов при привязке сокета, то с дополнительным конечным null  пути превышает
       длину sizeof(sun_path). В последствии при возврате адреса сокета (например, из accept(2)),
       если  входной  аргумент  addrlen  перед вызовом был равен sizeof(struct sockaddr_un), то в
       sun_path возвращаемой структуры адреса будет отсутствовать конечный null.

       Также, некоторые реализации не требуют наличия конечного null  при  привязке  сокета  (для
       определения  длины  sun_path  используется  аргумент  addrlen)  и когда в этих реализациях
       возвращается адрес сокета, то в sun_path также отсутствует конечный null.

       Приложения, которые получают адрес сокета могут содержать код (переносимый) для  обработки
       случая,  когда  нет  конечного  null в sun_path, учитывая фактическое количество пригодных
       байт в пути:

           strnlen(addr.sun_path, addrlen - offsetof(sockaddr_un, sun_path))

       Или  же  приложение  может  перед  получением  адреса  сокета   выделить   буфер   размера
       sizeof(struct sockaddr_un)+1, который будет обнулён перед возвращением. Возвращающий вызов
       может задать в addrlen значение sizeof(struct sockaddr_un), и дополнительный нулевой  байт
       здесь будет конечным null в строке, возвращаемой в sun_path:

           void *addrp;

           addrlen = sizeof(struct sockaddr_un);
           addrp = malloc(addrlen + 1);
           if (addrp == NULL)
               /* обработка ошибки */ ;
           memset(addrp, 0, addrlen + 1);

           if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == -1)
               /* обработка ошибки */ ;

           printf("sun_path = %s\n", ((struct sockaddr_un *) addrp)->sun_path);

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

ПРИМЕРЫ

       В  следующем  коде  демонстрируется  использование  пакето-упорядочивающих   сокетов   для
       локального  межпроцессного  обмена.  Он  состоит  из  двух программ. Программа-сервер ждёт
       подключения программы-клиента. Клиент посылает свой каждый  аргумент  командной  строки  в
       виде  отдельного сообщения. Сервер считает входящие сообщения как целые числа и складывает
       их. Клиент посылает строку-команду «END». Сервер посылает ответное  сообщение,  содержащее
       сумму  чисел  клиента.  Клиент  печатает сумму и завершает работу. Сервер ждёт подключение
       следующего клиента. Для остановки сервера, клиент вызывается с аргументом командной строки
       «DOWN».

       Следующий  вывод  был  записан при работе сервера в фоновом режиме и повторяющемся запуске
       клиента. Выполнение программы-сервера завершилось после получения им команды «DOWN».

   Пример вывода
           $ ./server &
           [1] 25887
           $ ./client 3 4
           Результат = 7
           $ ./client 11 -5
           Результат = 6
           $ ./client DOWN
           Результат = 0
           [1]+  Done                    ./server
           $

   Исходный код программы

       /*
        * Файл connection.h
        */

       #define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
       #define BUFFER_SIZE 12

       /*
        * Файл server.c
        */

       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>
       #include <sys/un.h>
       #include <unistd.h>
       #include "connection.h"

       int
       main(int argc, char *argv[])
       {
           struct sockaddr_un name;
           int down_flag = 0;
           int ret;
           int connection_socket;
           int data_socket;
           int result;
           char buffer[BUFFER_SIZE];

           /* Создание локального сокета. */

           connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
           if (connection_socket == -1) {
               perror("socket");
               exit(EXIT_FAILURE);
           }

           /*
            * Для переносимости очищаем всю структуру, так как в некоторых
            * реализациях имеются дополнительные (нестандартные) поля.
            */

           memset(&name, 0, sizeof(name));

           /* Привязываем сокет к имени сокета. */

           name.sun_family = AF_UNIX;
           strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);

           ret = bind(connection_socket, (const struct sockaddr *) &name,
                      sizeof(name));
           if (ret == -1) {
               perror("bind");
               exit(EXIT_FAILURE);
           }

           /*
            * Готовимся принимать подключения. Размер очереди (backlog)
            * устанавливаем равным 20. Пока один запрос обрабатывается, другие
            * запросы смогут подождать.
            */

           ret = listen(connection_socket, 20);
           if (ret == -1) {
               perror("listen");
               exit(EXIT_FAILURE);
           }

           /* Основной цикл обработки подключений. */

           for (;;) {

               /* Ожидание входящих подключений. */

               data_socket = accept(connection_socket, NULL, NULL);
               if (data_socket == -1) {
                   perror("accept");
                   exit(EXIT_FAILURE);
               }

               result = 0;
               for (;;) {

                   /* Ожидание следующего пакета с данными. */

                   ret = read(data_socket, buffer, sizeof(buffer));
                   if (ret == -1) {
                       perror("read");
                       exit(EXIT_FAILURE);
                   }

                   /* Проверяем, что буфер завершается 0. */

                   buffer[sizeof(buffer) - 1] = 0;

                   /* Обработка команд. */

                   if (!strncmp(buffer, "DOWN", sizeof(buffer))) {
                       down_flag = 1;
                       break;
                   }

                   if (!strncmp(buffer, "END", sizeof(buffer))) {
                       break;
                   }

                   /* Добавляем полученную команду. */

                   result += atoi(buffer);
               }

               /* Отправка результата. */

               sprintf(buffer, "%d", result);
               ret = write(data_socket, buffer, sizeof(buffer));
               if (ret == -1) {
                   perror("write");
                   exit(EXIT_FAILURE);
               }

               /* Закрытие сокета. */

               close(data_socket);

               /* Завершаем работу по команде DOWN. */

               if (down_flag) {
                   break;
               }
           }

           close(connection_socket);

           /* Удаляем сокет. */

           unlink(SOCKET_NAME);

           exit(EXIT_SUCCESS);
       }

       /*
        * Файл client.c
        */

       #include <errno.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>
       #include <sys/un.h>
       #include <unistd.h>
       #include "connection.h"

       int
       main(int argc, char *argv[])
       {
           struct sockaddr_un addr;
           int ret;
           int data_socket;
           char buffer[BUFFER_SIZE];

           /* Создание локального сокета. */

           data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
           if (data_socket == -1) {
               perror("socket");
               exit(EXIT_FAILURE);
           }

           /*
            * Для переносимости очищаем всю структуру, так как в некоторых
            * реализациях имеются дополнительные (нестандартные) поля.
            */

           memset(&addr, 0, sizeof(addr));

           /* Connect socket to socket address. */

           addr.sun_family = AF_UNIX;
           strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);

           ret = connect(data_socket, (const struct sockaddr *) &addr,
                          sizeof(addr));
           if (ret == -1) {
               fprintf(stderr, "The server is down.\n");
               exit(EXIT_FAILURE);
           }

           /* Посылаем аргументы. */

           for (size_t i = 1; i < argc; ++i) {
               ret = write(data_socket, argv[i], strlen(argv[i]) + 1);
               if (ret == -1) {
                   perror("write");
                   break;
               }
           }

           /* Отправка результата. */

           strcpy(buffer, "END");
           ret = write(data_socket, buffer, strlen(buffer) + 1);
           if (ret == -1) {
               perror("write");
               exit(EXIT_FAILURE);
           }

           /* Получение результата. */

           ret = read(data_socket, buffer, sizeof(buffer));
           if (ret == -1) {
               perror("read");
               exit(EXIT_FAILURE);
           }

           /* Проверяем, что буфер завершается 0. */

           buffer[sizeof(buffer) - 1] = 0;

           printf("Result = %s\n", buffer);

           /* Закрытие сокета. */

           close(data_socket);

           exit(EXIT_SUCCESS);
       }

       For examples of the use of SCM_RIGHTS, see cmsg(3)  and seccomp_unotify(2).

СМ. ТАКЖЕ

       recvmsg(2),    sendmsg(2),    socket(2),    socketpair(2),    cmsg(3),    capabilities(7),
       credentials(7), socket(7), udp(7)

ПЕРЕВОД

       Русский    перевод    этой    страницы    руководства    был    сделан   Azamat   Hackimov
       <azamat.hackimov@gmail.com>,   Dmitriy    Ovchinnikov    <dmitriyxt5@gmail.com>,    Dmitry
       Bolkhovskikh  <d20052005@yandex.ru>,  Katrin Kutepova <blackkatelv@gmail.com>, Yuri Kozlov
       <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

       Этот  перевод  является  бесплатной  документацией;  прочитайте  Стандартную  общественную
       лицензию GNU версии 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы
       узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если вы обнаружите ошибки в переводе  этой  страницы  руководства,  пожалуйста,  отправьте
       электронное письмо на ⟨man-pages-ru-talks@lists.sourceforge.net⟩.