Provided by: manpages-pl_4.15.0-9_all bug

NAZWA

       unix - gniazda lokalnej komunikacji międzyprocesowej

SKŁADNIA

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

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

OPIS

       Rodzina  gniazd  AF_UNIX  (znana  również  jako  AF_LOCAL)  służy  do wydajnej komunikacji
       pomiędzy procesami na tej samej maszynie. Zgodnie z  tradycją,  gniazda  domeny  uniksowej
       mogą  być  albo  anonimowe  (tworzone przez socketpair(2)), albo skojarzone z plikiem typu
       gniazda. Linux wspiera również abstrakcyjną przestrzeń nazw, niezależną od systemu plików.

       Poprawne  typy  gniazd  w  domenie  Uniksa  to:  SOCK_STREAM  dla  gniazd  strumieniowych,
       SOCK_DGRAM  dla   gniazd  datagramowych,  które zachowują granice komunikatów (w przypadku
       większości implementacji Uniksa gniazda uniksowe są  zawsze  niezawodne  i  nie  zmieniają
       kolejności  datagramów), oraz (od wersji Linuksa 2.6.4) SOCK_SEQPACKET dla gniazd pakietów
       sekwencyjnych  zorientowanych  połączeniowo,  które   zachowują   granice   komunikatu   i
       dostarczają komunikaty w kolejności ich wysyłania.

       Za  pośrednictwem  pomocniczych danych można przez gniazda domeny uniksowej przekazywać do
       innych procesów deskryptory plików i uwierzytelnienia procesów.

   Format adresu
       Adres gniazda domeny uniksowej jest reprezentowany przez następującą strukturę:

           struct sockaddr_un {
               sa_family_t sun_family;               /* AF_UNIX */
               char        sun_path[108];            /* Pathname */
           };

       Pole sun_family zawsze zawiera AF_UNIX. W Linuksie sun_path ma rozmiar  108  bajtów,  zob.
       też UWAGI poniżej.

       Różne  wywołania  systemowe  (np.  bind(2),  connect(2)  i  sendto(2))  przyjmują argument
       sockaddr_un  jako  wejście.  Niektóre  inne  wywołania  systemowe   (np.   getsockname(2),
       getpeername(2), recvfrom(2) i accept(2)) zwracają argument tego typu.

       W strukturze sockaddr_un rozróżniane są trzy typy adresów:

       *  pathname: gniazdo domeny uniksowej może zostać związane z zakończoną znakiem NULL nazwą
          ścieżki systemowej za pomocą bind(2). Jeśli adres ścieżki gniazda jest zwracany  (przez
          jedno z ww. wywołań systemowych) to jego długością jest

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

          a  sun_path  zawiera zakończoną null ścieżkę. (W Linuksie powyższe wyrażenie offsetof()
          jest równe tej samej wartości co sizeof(sa_family_t), lecz niektóre inne  implementacje
          dołączają inne  pola  przed  sun_path,  więc  bardziej przenośnie, wyrażenie offsetof()
          opisuje rozmiar struktury adresu).

          Więcej informacji o ścieżkach gniazd znajduje się poniżej.

       *  unnamed: Gniazdo strumieniowe nie związane z nazwą ścieżki za pomocą bind(2)  nie  jest
          nazwane. Podobnie dwa gniazda utworzone przez socketpair(2) nie są nazwane. Jeśli adres
          nienazwanego gniazda jest zwracany,  to  jego  długością  jest  sizeof(sa_family_t),  a
          zawartość sun_path nie powinna być sprawdzana.

       *  abstract:  adres gniazda abstrakcyjnego jest rozróżniany (od adresu ścieżki) po tym, że
          sun_path[0] jest bajtem NULL ('\0'). Adres gniazda  znajduje  się  w  przestrzeni  nazw
          podanej  w  dodatkowych  bajtach  w  sun_path, które są pokryte przez długość struktury
          adresu (Bajty NULL w nazwie nie mają  żadnego  specjalnego  znaczenia).  Nazwa  nie  ma
          żadnego   powiązania   z   nazwą  pliku  w  systemie  plików.  Zwracany  adres  gniazda
          abstrakcyjnego ma w polu addrlen ustawioną długość większą niż sizeof(sa_family_t) (tj.
          większą   niż   2),   a   nazwa   gniazda   zawarta   jest   w  pierwszych  (addrlen  -
          sizeof(sa_family_t)) bajtach pola sun_path.

   Ścieżki gniazd
       Przy przypisywaniu  gniazda  do  ścieżki  powinno  się przestrzegać  kilku  zasad  w  celu
       maksymalnej przenośności i łatwości programowania:

       *  Ścieżka w sun_path powinna być zakończona znakiem NULL.

       *  Długość ścieżki, w tym kończący bajt null nie powinna przekraczać rozmiaru sun_path.

       *  Argument  addrlen  opisujący  obejmującą strukturę  sockaddr_un  powinien  mieć wartość
          przynajmniej:

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

          lub, prościej, addrlen powinien być podany jako sizeof(struct sockaddr_un).

       W różnych implementacjach różnie obsługiwane są adresy  gniazd  domen  Uniksa,  które  nie
       przestrzegają  powyższych zaleceń. Na przykład niektóre (lecz nie wszystkie) implementacje
       dodają kończący znak null, jeśli nie jest on obecny w przekazanej sun_path.

       Przy programowaniu przenośnych aplikacji proszę wziąć pod uwagę, że niektóre implementację
       mają sun_path o długości zaledwie 92 bajtów.

       Różne   wywołania   systemowe  (accept(2),  recvfrom(2),  getsockname(2),  getpeername(2))
       zwracają struktury adresów gniazd. Gdy chodzi o gniazda  domeny  Uniksa,  wartość-rezultat
       argumentu  addrlen  umieszczonego  w  wywołaniu  powinna  być zainicjowana  jw.  Gdy  jest
       zwracany, argument ten jest ustawiany aby przedstawiać aktualny rozmiar struktury  adresu.
       Wywołujący  powinien  sprawdzić wartość zwracaną w tym argumencie, jeśli wartość wyjściowa
       przekracza wartość wejściową, to nie ma gwarancji, że kończący znak  null  jest  obecny  w
       sun_path (zob PROBLEMY).

   Pathname socket ownership and permissions
       In  the Linux implementation, pathname sockets honor the permissions of the directory they
       are in.  Creation of a new socket fails if the process does  not  have  write  and  search
       (execute) permission on the directory in which the socket is created.

       On  Linux,  connecting to a stream socket object requires write permission on that socket;
       sending a datagram to a datagram socket likewise requires write permission on that socket.
       POSIX  does  not  make any statement about the effect of the permissions on a socket file,
       and on some systems (e.g., older BSDs), the  socket  permissions  are  ignored.   Portable
       programs should not rely on this feature for security.

       When  creating  a  new socket, the owner and group of the socket file are set according to
       the usual rules.  The socket file has all permissions enabled, other than those  that  are
       turned off by the process umask(2).

       The owner, group, and permissions of a pathname socket can be changed (using chown(2)  and
       chmod(2)).

   Abstract sockets
       Socket permissions have no meaning for abstract sockets:  the  process  umask(2)   has  no
       effect  when binding an abstract socket, and changing the ownership and permissions of the
       object (via fchown(2)  and fchmod(2)) has no effect on the accessibility of the socket.

       Abstract sockets automatically disappear when  all  open  references  to  the  socket  are
       closed.

       The abstract socket namespace is a nonportable Linux extension.

   Opcje gniazda
       Ze  względów  historycznych  następujące  opcje  gniazd są podawane przy typie SOL_SOCKET,
       pomimo że są one specyficzne dla AF_UNIX. Można je  ustawić  za  pomocą  setsockopt(2),  a
       odczytać za pomocą getsockopt(2), podając SOL_SOCKET jako rodzinę gniazd.

       SO_PASSCRED
              Enabling  this  socket  option  causes  receipt  of  the credentials of the sending
              process in an SCM_CREDENTIALS  ancillary  message  in  each  subsequently  received
              message.   The  returned  credentials  are  those  specified  by  the  sender using
              SCM_CREDENTIALS, or a default that includes the sender's PID,  real  user  ID,  and
              real group ID, if the sender did not specify SCM_CREDENTIALS ancillary data.

              Przy włączonej tej opcji i niepołączonym jeszcze gnieździe, unikatowa nazwa gniazda
              z abstrakcyjnej przestrzeni nazw jest generowana automatycznie.

              The value given as an argument to setsockopt(2)  and  returned  as  the  result  of
              getsockopt(2)  is an integer boolean flag.

       SO_PASSSEC
              Enables  receiving of the SELinux security label of the peer socket in an ancillary
              message of type SCM_SECURITY (see below).

              The value given as an argument to setsockopt(2)  and  returned  as  the  result  of
              getsockopt(2)  is an integer boolean flag.

              The  SO_PASSSEC  option  is  supported for UNIX domain datagram sockets since Linux
              2.6.18; support for UNIX domain stream sockets was added in Linux 4.2.

       SO_PEEK_OFF
              Patrz socket(7).

       SO_PEERCRED
              This read-only socket option returns the credentials of the peer process  connected
              to this socket.  The returned credentials are those that were in effect at the time
              of the call to connect(2)  or socketpair(2).

              The argument to getsockopt(2)  is a  pointer  to  a  ucred  structure;  define  the
              _GNU_SOURCE  feature  test  macro  to  obtain the definition of that structure from
              <sys/socket.h>.

              The use of this option is possible only for connected AF_UNIX  stream  sockets  and
              for AF_UNIX stream and datagram socket pairs created using 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).

   Automatyczne przypisywanie adresów
       Jeśli  w  wywołaniu  bind(2)  podane  zostanie addrlen równe sizeof(sa_family_t) lub opcja
       SO_PASSCRED gniazda była ustawiona dla gniazda nieprzypisanego do  adresu,  wtedy  gniazdo
       jest  automatycznie  przypisywane  do  adresu abstrakcyjnego. Adres ten składa się z bajtu
       NULL, po którym następuje 5 bajtów ze zbioru znaków  [0-9a-f].  W  związku  z  tym  liczba
       automatycznie  przypisywanych  adresów  jest ograniczona przez 2^20. (W Linuksie 2.1.15, w
       którym dodano możliwość automatycznego  przypisywania  adresów,  i  w  kolejnych  wersjach
       używane  było  8  bajtów, a limit wynosił 2^32 adresów. Zostało to zmienione na 5 bajtów w
       Linuksie 2.3.15).

   API gniazd
       W kolejnych paragrafach opisano pewne  szczegóły  implementacji  API  gniazd  domeny  UNIX
       specyficzne dla Linuksa oraz cechy niewspierane.

       Gniazda  z  domeny  uniksowej  nie  obsługują zawiadomienia o danych autonomicznych (flaga
       MSG_OOB funkcji send(2) i recv(2)).

       Flaga MSG_MORE funkcji send(2) nie jest obsługiwana dla gniazd domeny uniksowej.

       Before Linux 3.4, the use of MSG_TRUNC in the flags argument of recv(2)  was not supported
       by UNIX domain sockets.

       Opcja  SO_SNDBUF  działa w przypadku gniazd domeny uniksowej, ale opcja SO_RCVBUF już nie.
       Dla gniazd datagramowych wartość SO_SNDBUF nakłada górny  limit  na  rozmiar  wychodzących
       datagramów. Limit ten jest liczony jako podwojona (patrz socket(7)) wartość opcji minus 32
       bajty wymagane na informacje nie będące danymi.

   Komunikaty pomocnicze
       Dane pomocnicze są wysyłane i odbierane za pomocą sendmsg(2)  i  recvmsg(2).  Ze  względów
       historycznych  komunikaty  pomocnicze  poniższych typów są podawane przy typie SOL_SOCKET,
       pomimo że są one specyficzne dla AF_UNIX. Aby je wysłać, należy  ustawić  pole  cmsg_level
       struktury  cmsghdr na SOL_SOCKET, a pole cmsg_type na typ. Więcej informacji można znaleźć
       w cmsg(3).

       SCM_RIGHTS
              Odbieranie od innego procesu lub wysyłanie do niego zbioru  otwartych  deskryptorów
              plików.  Porcja  danych  zawiera  tablicę  liczb całkowitych będących deskryptorami
              plików.

              Commonly, this operation is referred to as "passing a file descriptor"  to  another
              process.   However, more accurately, what is being passed is a reference to an open
              file description (see open(2)), and in the receiving process it is  likely  that  a
              different  file  descriptor  number  will be used.  Semantically, this operation is
              equivalent to duplicating (dup(2))  a file  descriptor  into  the  file  descriptor
              table of another process.

              If the buffer used to receive the ancillary data containing file descriptors is too
              small (or is absent), then the ancillary data is truncated (or discarded)  and  the
              excess file descriptors are automatically closed in the receiving process.

              If  the  number  of file descriptors received in the ancillary data would cause the
              process to exceed its RLIMIT_NOFILE resource limit (see getrlimit(2)),  the  excess
              file descriptors are automatically closed in the receiving process.

              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 in kernels
              before 2.6.38).

       SCM_CREDENTIALS
              Odbieranie lub wysyłanie uwierzytelnień uniksowych.  Może  służyć  do  autoryzacji.
              Uwierzytelnienia  są  przekazywane  jako  komunikat  pomocniczy  typu struct ucred,
              zdefiniowanego w <sys/socket.h> następująco:

                  struct ucred {
                      pid_t pid;  /* identyfikator procesu wysyłającego */
                      uid_t uid;  /* ident. użytkownika procesu wysyłającego */
                      gid_t gid;  /* ident. grupy procesu wysyłającego */
                  };

              Począwszy od wersji 2.8 biblioteki glibc, aby uzyskać dostęp do definicji powyższej
              struktury,  należy  zdefiniować  makro _GNU_SOURCE (przed dołączeniem jakichkolwiek
              plików nagłówkowych).

              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).

              To  receive  a  struct ucred message, the SO_PASSCRED option must be enabled on the
              socket.

       SCM_SECURITY
              Receive the SELinux security context (the security label)  of the peer socket.  The
              received  ancillary  data  is  a  null-terminated  string  containing  the security
              context.  The receiver should allocate at least NAME_MAX bytes in the data  portion
              of the ancillary message for this data.

              To  receive  the  security  context,  the  SO_PASSSEC option must be enabled on the
              socket (see above).

       When sending ancillary data with sendmsg(2), only one item of each of the above types  may
       be included in the sent message.

       At least one byte of real data should be sent when sending ancillary data.  On Linux, this
       is required to successfully send ancillary data over a UNIX domain  stream  socket.   When
       sending ancillary data over a UNIX domain datagram socket, it is not necessary on Linux to
       send any accompanying real data.  However, portable applications should  also  include  at
       least one byte of real data when sending ancillary data over a datagram socket.

       When  receiving  from  a  stream  socket,  ancillary  data forms a kind of barrier for the
       received data.  For example, suppose that the sender transmits as follows:

              1. sendmsg(2)  of four bytes, with no ancillary data.
              2. sendmsg(2)  of one byte, with ancillary data.
              3. sendmsg(2)  of four bytes, with no ancillary data.

       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.

       If  the  space  allocated  for  receiving  incoming  ancillary  data is too small then the
       ancillary data is truncated to the number of headers that will fit in the supplied  buffer
       (or,  in  the case of an SCM_RIGHTS file descriptor list, the list of file descriptors may
       be truncated).   If  no  buffer  is  provided  for  incoming  ancillary  data  (i.e.,  the
       msg_control  field  of  the  msghdr  structure  supplied to recvmsg(2)  is NULL), then the
       incoming ancillary data is discarded.  In both of these cases, the MSG_CTRUNC flag will be
       set in the msg.msg_flags value returned by recvmsg(2).

   Kontrolki systemowe (ioctl)
       Następujące  wywołania  ioctl(2) zwracają informacje w parametrze value. Poprawna składnia
       to:

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

       ioctl_type może przyjmować wartość:

       SIOCINQ
              For SOCK_STREAM sockets, this call returns  the  number  of  unread  bytes  in  the
              receive  buffer.   The  socket  must  not  be  in  LISTEN state, otherwise an error
              (EINVAL)  is returned.  SIOCINQ is defined  in  <linux/sockios.h>.   Alternatively,
              you  can  use  the  synonymous  FIONREAD, defined in <sys/ioctl.h>.  For SOCK_DGRAM
              sockets, the returned value is the same as for Internet  domain  datagram  sockets;
              see udp(7).

BŁĘDY

       EADDRINUSE
              Podany adres lokalny jest zajęty lub obiekt gniazda w systemie plików już istnieje.

       EBADF  This  error  can  occur for sendmsg(2)  when sending a file descriptor as ancillary
              data over a UNIX domain socket (see the  description  of  SCM_RIGHTS,  above),  and
              indicates that the file descriptor number that is being sent is not valid (e.g., it
              is not an open file descriptor).

       ECONNREFUSED
              Adres zdalny podany w connect(2) nie odnosił się do  gniazda  nasłuchującego.  Błąd
              może także wystąpić jeśli docelowa ścieżka nie jest gniazdem.

       ECONNRESET
              Zdalne gniazdo zostało nieoczekiwanie zamknięte.

       EFAULT Nieprawidłowy adres pamięci użytkownika.

       EINVAL Podano  nieprawidłowy argument. Najczęstszą przyczyną jest brak ustawionego AF_UNIX
              w polu sun_type przekazywanych gniazdu adresów lub nieprawidłowy dla danej operacji
              stan gniazda.

       EISCONN
              Wywołano  connect(2)  dla  już  połączonego  gniazda  lub podano adres docelowy dla
              połączonego gniazda.

       ENOENT Nie istnieje ścieżka dla zdalnego adresu przekazanego do connect(2).

       ENOMEM Brak pamięci.

       ENOTCONN
              Operacja na gnieździe wymaga adresu docelowego, a gniazdo nie jest połączone.

       EOPNOTSUPP
              Operacja strumieniowa wywołana dla gniazda niestrumieniowego lub próba użycia opcji
              danych autonomicznych.

       EPERM  Wysyłający podał nieprawidłowe uwierzytelnienia w struct ucred.

       EPIPE  Zdalne   gniazdo  strumieniowe  zostało  zamknięte.  Gdy  włączone,  wysyłany  jest
              jednocześnie sygnał SIGPIPE. Można tego uniknąć, przekazując znacznik  MSG_NOSIGNAL
              do send(2) lub sendmsg(2).

       EPROTONOSUPPORT
              Podanym protokołem nie jest AF_UNIX.

       EPROTOTYPE
              Typ  gniazda  zdalnego  różni  się  od  typu  gniazda  lokalnego  (SOCK_DGRAM wobec
              SOCK_STREAM).

       ESOCKTNOSUPPORT
              Nieznany typ gniazda.

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

       ETOOMANYREFS
              This  error  can  occur for sendmsg(2)  when sending a file descriptor as ancillary
              data over a UNIX domain socket (see the  description  of  SCM_RIGHTS,  above).   It
              occurs  if  the  number  of  "in-flight" file descriptors exceeds the RLIMIT_NOFILE
              resource limit and the caller does not have the  CAP_SYS_RESOURCE  capability.   An
              in-flight  file  descriptor is one that has been sent using sendmsg(2)  but has not
              yet been accepted in the recipient process using recvmsg(2).

              This error is diagnosed since mainline  Linux  4.5  (and  in  some  earlier  kernel
              versions  where  the  fix has been backported).  In earlier kernel versions, it was
              possible to place an unlimited number of file descriptors  in  flight,  by  sending
              each  file descriptor with sendmsg(2)  and then closing the file descriptor so that
              it was not accounted against the RLIMIT_NOFILE resource limit.

       Inne błędy mogą zostać wygenerowane przez  podstawową  warstwę  gniazd  lub  przez  system
       plików  podczas  tworzenia  obiektu  gniazda  w  systemie  plików. Więcej informacji można
       znaleźć na odpowiednich stronach podręcznika.

WERSJE

       SCM_CREDENTIALS oraz abstrakcyjna przestrzeń nazw zostały wprowadzone w Linuksie 2.2 i nie
       należy  ich używać w przenośnych programach. (Niektóre systemy wywodzące się z BSD również
       wspierają przekazywanie uwierzytelnień, ale implementacje różnią się szczegółami).

UWAGI

       W trakcie łączenia się z gniazdem mającym  przypisaną  nazwę  pliku,  tworzony  jest  plik
       specjalny  gniazda  w  systemie  plików,  który musi zostać usunięty (za pomocą unlink(2))
       przez wywołującego, gdy już nie będzie potrzebny. Stosuje się tu zwykła uniksowa  składnia
       opóźnionego  zamknięcia  (ang.  close-behind): gniazdo można skasować w dowolnym momencie,
       ale zostanie ono ostatecznie usunięte z systemu plików po zamknięciu ostatniego  odwołania
       do niego.

       Aby   przekazać   deskryptory  plików  lub  uwierzytelnienia  poprzez  SOCK_STREAM  trzeba
       wysłać/odebrać co najmniej  jeden  bajt  niepomocniczych  danych  w  tym  samym  wywołaniu
       sendmsg(2) lub recvmsg(2)

       Gniazda   strumieniowe   z   domeny   uniksowej   nie  obsługują  zawiadomienia  o  danych
       autonomicznych.

BŁĘDY

       Przy wiązaniu gniazda z adresem, Linux  jest  jedną z  implementacji  dodających  kończące
       null,  jeśli  nie  poda się go w sun_path. Zwykle jest to bezproblemowe, gdy adres gniazda
       jest pozyskiwany będzie on o jeden bajt dłuższy niż podawany początkowo. Jest jednak jeden
       przypadek  mogący  spowodować  mylące zachowanie: jeśli podany zostanie adres 108 bajtowy,
       bez znaku null, to dodanie znaku null spowodowałoby przekroczenie  długości  ścieżki  poza
       sizeof(sun_path).   W   konsekwencji,   przy  pozyskiwaniu  adresu  gniazda  (np.  poprzez
       accept(2)), jeśli wejściowy argument addrlen dla pozyskiwanego wywołania jest podany  jako
       sizeof(struct  sockaddr_un), to zwrócona struktura adresu nie będzie miała kończącego null
       w sun_path.

       Dodatkowo, niektóre implementacje  nie  wymagają kończącego  null  przy  wiązaniu  gniazda
       (argument   addrlen   jest  używany  do  określenia  długości  sun_path),  a  gdy  w  tych
       implementacjach jest pozyskiwany adres gniazda, to nie ma kończącego null w sun_path.

       Aplikacje pozyskujące adresy gniazd mogą posiadać (przenośny) kod do  obsługi  możliwości,
       że  w  sun_path  nie  ma  kończącego null zauważając fakt, że liczba prawidłowych bajtów w
       ścieżce to:

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

       Alternatywnie,  aplikacja  może  pozyskać  adres  gniazda  przez  przydzielenie  buforu  o
       rozmiarze   sizeof(struct   sockaddr_un)+1   który   jest  wyzerowany  przed  pozyskaniem.
       Pobierające wywołanie może określić addrlen jako sizeof(struct sockaddr_un),  a  dodatkowy
       bajt zero zapewnia, że w łańcuchu zwróconym w sun_path będzie kończące null:

           void *addrp;

           addrlen = sizeof(struct sockaddr_un);
           addrp = malloc(addrlen + 1);
           if (addrp == NULL)
               /* Obsługa błędu */ ;
           memset(addrp, 0, addrlen + 1);

           if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == -1)
               /* obsługa błędu */ ;

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

       Tego  bałaganu  można  uniknąć,  jeśli  jest pewność, że aplikacja tworząca ścieżki gniazd
       przestrzega reguł opisanych powyżej rozdziale Ścieżki gniazd.

PRZYKŁADY

       Poniższy kod demonstruje użycie gniazd  pakietów  sekwencyjnych  do  lokalnej  komunikacji
       międzyprocesowej.  Składa  się  z  dwóch  programów. Serwer czeka na połączenie z programu
       klienckiego. Klient wysyła każdy  ze  swoich  argumentów  wiersza  poleceń  w  oddzielnych
       wiadomościach.  Serwer traktuje przychodzące wiadomości jako liczby całkowite i dodaje je.
       Klient wysyła łańcuch polecenia "END". Serwer odsyła komunikat zawierający sumę klienckich
       liczb  całkowitych.  Klient  wypisuje  sumę  i  wychodzi.  Serwer  czeka  na połączenie od
       kolejnego klienta. Aby zatrzymać serwer,  klient  jest  wywoływany  z  argumentem  wiersza
       poleceń "DOWN".

       Podczas  działania serwera w tle i kolejnych uruchomień klienta zarejestrowano następujące
       wyjście. Wykonywanie programu serwera kończy się, gdy otrzymuje on polecenie "DOWN".

   Przykładowe wyjście
           $ ./server &
           [1] 25887
           $ ./client 3 4
           Result = 7
           $ ./client 11 -5
           Result = 6
           $ ./client DOWN
           Result = 0
           [1]+  Done                    ./server
           $

   Kod źródłowy programu

       /*
        * Plik connection.h
        */

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

       /*
        * Plik 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];

           /* Tworzenie lokalnego gniazda. */

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

           /*
            * Dla przenośności wyczyść całą strukturę, ponieważ niektóre
            * implementacje mają dodatkowe (niestandardowe) pola
            * w strukturze.
            */

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

           /* Wiązanie gniazda z nazwą gniazda. */

           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);
           }

           /*
            * Przygotowywanie do akceptowania połączeń. Rozmiar bufora jest
            * ustawiany na 20. Podczas przetwarzania jednego żądania, inne
            * mogą czekać.
            */

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

           /* To główna pętla do obsługi połączeń. */

           for (;;) {

               /* Czekanie na połączenie przychodzące. */

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

               result = 0;
               for (;;) {

                   /* Czekanie na następny pakiet danych. */

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

                   /* Upewnienie się, że bufor kończy się 0. */

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

                   /* Obsługa poleceń. */

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

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

                   /* Dodawanie otrzymanej sumy. */

                   result += atoi(buffer);
               }

               /* Wysyłanie wyniku. */

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

               /* Zamknięcie gniazda. */

               close(data_socket);

               /* Wyjście po poleceniu DOWN. */

               if (down_flag) {
                   break;
               }
           }

           close(connection_socket);

           /* Usunięcie gniazda. */

           unlink(SOCKET_NAME);

           exit(EXIT_SUCCESS);
       }

       /*
        * Plik 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];

           /* Tworzenie lokalnego gniazda. */

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

           /*
            * Dla przenośności wyczyść całą strukturę, ponieważ niektóre
            * implementacje mają dodatkowe (niestandardowe) pola
            * w strukturze.
            */

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

           /* Łączenie gniazda z adresem gniazda. */

           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);
           }

           /* Wysyłanie argumentów. */

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

           /* Żądanie wyniku. */

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

           /* Otrzymanie wyniku. */

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

           /* Upewnienie się, że bufor kończy się 0. */

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

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

           /* Zamknięcie gniazda. */

           close(data_socket);

           exit(EXIT_SUCCESS);
       }

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

ZOBACZ TAKŻE

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

O STRONIE

       Angielska  wersja  tej  strony  pochodzi  z  wydania  5.13  projektu Linux man-pages. Opis
       projektu, informacje dotyczące zgłaszania błędów oraz  najnowszą  wersję  oryginału  można
       znaleźć pod adresem https://www.kernel.org/doc/man-pages/.

TŁUMACZENIE

       Autorami  polskiego  tłumaczenia  niniejszej strony podręcznika są: Andrzej Krzysztofowicz
       <ankry@green.mf.pg.gda.pl>,   Robert   Luberda   <robert@debian.org>   i   Michał   Kułach
       <michal.kulach@gmail.com>

       Niniejsze  tłumaczenie  jest  wolną  dokumentacją. Bliższe informacje o warunkach licencji
       można   uzyskać   zapoznając   się   z   GNU   General   Public   License   w   wersji   3
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   lub   nowszej.   Nie  przyjmuje  się  ŻADNEJ
       ODPOWIEDZIALNOŚCI.

       Błędy w tłumaczeniu  strony  podręcznika  prosimy  zgłaszać  na  adres  listy  dyskusyjnej
       ⟨manpages-pl-list@lists.sourceforge.net⟩.