Provided by: manpages-ja_0.5.0.0.20221215+dfsg-1_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 では、ファイル システムに依存しない抽象名前空間 (abstract namespace)  もサポートして
       いる。

       Valid  socket  types  in  the  UNIX domain are: SOCK_STREAM, for a stream-oriented socket;
       SOCK_DGRAM, for a datagram-oriented socket that preserves message boundaries (as  on  most
       UNIX  implementations,  UNIX domain datagram sockets are always reliable and don't reorder
       datagrams); and (since Linux 2.6.4)  SOCK_SEQPACKET, for a sequenced-packet socket that is
       connection-oriented, preserves message boundaries, and delivers messages in the order that
       they were sent.

       UNIX ドメインソケットでは、補助データを使って ファイルディスクリプターや  プロセスの信任状
       (credential) を 送受信することもできる。

   アドレスのフォーマット
       UNIX ドメインソケットのアドレスは以下の構造体で表現される。

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

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

       様々なシステムコール (例えば bind(2), connect(2), sendto(2)) は入力として sockaddr_un 引数
       を取る。 他のいくつかのシステムコール (例えば getsockname(2), getpeername(2), recvfrom(2),
       accept(2)) はこの型の引数を返す。

       sockaddr_un 構造体では 3 種類のアドレスが区別される。

       *  pathname (パス名): bind(2) を使って、UNIX ドメインソケットを、 ヌル終端されたファイルシ
          ステム上のパス名に結び付けることができる。   (上述のいずれかのシステムコールにより)  ソ
          ケットのアドレスが返される際、 その長さは

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

          であり、 sun_path にはヌル終端されたパス名が格納される。 (Linux では、上記の offsetof()
          式は  sizeof(sa_family_t) の値と同じだが、 他の実装では sun_path の前に他のフィールドが
          含まれる場合もある。 そのため、 offsetof() 式を使う方がより移植性のある方法でアドレス構
          造体のサイズを知ることができる。)

          パス名ソケットの詳細については、後で説明する。

       *  unnamed  (名前なし):  bind(2)  を使ってパス名に結び付けることができないストリーム型のソ
          ケットは 名前を持たない。同様に、 socketpair(2)  で作成される 2  つのソケットも名前を持
          たない。 名前なしのソケットのアドレスを返す際には、 その長さは sizeof(sa_family_t) であ
          り、 sun_path は検査すべきではない。

       *  abstract (抽象): 抽象ソケットアドレスは、 sun_path[0] がヌルバイト ('\0')  であることか
          ら    (パス名ソケットから)    区別できる。   この名前空間におけるソケットのアドレスは、
          sun_path の残りのバイトの、 アドレス構造体の指定された長さの範囲で表される  (名前中のヌ
          ルバイトには特別な意味はない)。  この名前はファイルシステムのパス名とは何の関係もない。
          抽象ソケットのアドレスを返される際には、 返される addrlensizeof(sa_family_t) より大
          きく   (つまり   2   より大きく)、   ソケットの名前は   sun_path  の最初の  (addrlen  -
          sizeof(sa_family_t)) バイトに格納される。

   パス名ソケット
       ソケットにパス名を結びつける際に、  最大限の移植性を持たせ、コーディングを簡単にするための
       ルールがいくつかある。

       *  sun_path のパス名はヌル終端すべきである。

       *  終端のヌルバイトを含めたパス名の長さは sun_path の大きさを超えないようにすべきである。

       *  sockaddr_un 構造体の終わりを示す addrlen 引数は最低でも以下の値を持つべきである。

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

          もしくは、もっと簡単には、  addrlensizeof(struct sockaddr_un) を指定することもでき
          る。

       UNIX ドメインソケットアドレスの扱いが上記のルールに従っていない実装もいくつかある。  (全部
       ではないが)  いくつかの実装では、 sun_path に文字列終端の NULL がなかった場合に終端の NULL
       が追加される。

       移植性があるアプリケーションを作成する際には、 いくつかの実装では sun_path は 92  バイトし
       かないという点にも留意しておくとよい。

       様々なシステムコール (accept(2), recvfrom(2), getsockname(2), getpeername(2)) がソケットア
       ドレス構造体を返す。  これらのシステムコールが  UNIX  ドメインソケットに対して呼ばれた際に
       は、  これらの呼び出しに渡す addrlen 引数は上記の説明のように初期化すべきである。 リターン
       時には、この引数にはアドレス構造体の「実際の」サイズが設定される。  呼び出し側ではこの引数
       で返された値を確認すべきである。  返された値が入力値よりも大きい場合、  sun_path  に終端の
       NULL バイトが存在する保証はない (「バグ」を参照)。

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

   抽象ソケット
       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.

   ソケットオプション
       歴史的な理由により、これらのオプションは   たとえ    AF_UNIX    固有のオプションであっても
       SOL_SOCKET 型で指定する。 ソケットファミリーとして SOL_SOCKET を指定すると、 setsockopt(2)
       でオプションが設定でき、 getsockopt(2)  で取得ができる。

       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.

              このオプションがセットされていて、まだソケットが接続されていないと、抽象名前空間に
              他と重ならない名前が自動的に生成される。

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

   自動バインド (autobind) 機能
       bind(2) 呼び出しで sizeof(sa_family_t) として addrlen を指定するか、  アドレスに明示的にバ
       インドされていないソケットに対して SO_PASSCRED ソケットオプションが指定されていた場合、 そ
       のソケットは抽象アドレスに自動的にバインドされる。  このアドレスは、1   個のヌルバイトの後
       に、文字集合  [0-9a-f] のバイトが 5 個続く形式である。したがって、自動的にバインドされるア
       ドレス数には 2^20 個という上限が存在する。 (Linux 2.1.15  以降で、自動バインド機能が追加さ
       れたときには、   8  バイトが使われており、自動バインドアドレス数の上限は  2^32  であった。
       Linux 2.3.15 で 5 バイトに変更された。)

   ソケット API
       この節では、Linux の UNIX ドメインソケットでの、ドメイン固有の詳細仕様と ソケット API でサ
       ポートされていない機能について説明する。

       UNIX  ドメインソケットでは、帯域外データ (out-of-band data) の 送信 (send(2) と recv(2) の
       MSG_OOB フラグ) はサポートされていない。

       send(2) MSG_MORE フラグは UNIX ドメインソケットではサポートされていない。

       Linux 3.4 より前では、 recv(2) の flags 引数での MSG_TRUNC の使用は UNIX  ドメインソケット
       ではサポートされていなかった。

       SO_SNDBUF  ソケットオプションは UNIX ドメインソケットで効果を持つが、 SO_RCVBUF は効果がな
       い。 データグラムソケットでは、 SO_SNDBUF の値が 出力データグラムの上限サイズとなる。 実際
       の上限値は、 SO_SNDBUF オプション として設定された値の 2倍 (socket(7) 参照) からオーバヘッ
       ドとして使用される 32 バイトを引いた値となる。

   補助メッセージ
       補助データを送受するには、 sendmsg(2)  や recvmsg(2)  を使用する。  歴史的な理由により、以
       下に示す補助メッセージの型は たとえ AF_UNIX 固有のものであっても SOL_SOCKET 型で指定する。
       これらを送るには、構造体  cmsghdrcmsg_level  フィールドに  SOL_SOCKET   をセットし、
       cmsg_type フィールドにタイプをセットする。 詳細は cmsg(3)  を見よ。

       SCM_RIGHTS
              他のプロセスでオープンされたファイルディスクリプターのセットを送受信する。 データ部
              分にファイルディスクリプターの整数配列が入っている。

              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
              UNIX 信任状を送受信する。これは認証に用いることができる。 信任状は struct ucred  の
              補助メッセージとして渡される。 この構造体は <sys/socket.h> で以下のように定義されて
              いる。

                  struct ucred {
                      pid_t pid;    /* Process ID of the sending process */
                      uid_t uid;    /* User ID of the sending process */
                      gid_t gid;    /* Group ID of the sending process */
                  };

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

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

   ioctl
       以下の ioctl(2) 呼び出しは value に情報を入れて返す。 正しい書式は以下の通り。

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

       ioctl_type には以下を指定できる:

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

エラー

       EADDRINUSE
              指定したローカルアドレスが既に使用されているか、ファイルシステムの ソケットオブジェ
              クトが既に存在している。

       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
              connect(2)  により指定されたリモートアドレスが接続待ちソケットではなかった。 このエ
              ラーはターゲットのパス名がソケットでなかった場合にも発生する。

       ECONNRESET
              リモートソケットが予期しないかたちでクローズされた。

       EFAULT ユーザーメモリーアドレスが不正。

       EINVAL 渡した引数が不正。よくある原因としては、渡したアドレスの  sun_type  フィール   ドに
              AF_UNIX が指定されていなかった、行おうとした操作に対してソケットが有 効な状態ではな
              かった、など。

       EISCONN
              既に接続されているソケットに対して connect(2)  が呼ばれた。または、指定したターゲッ
              トアドレスが 既に接続済みのソケットだった。

       ENOENT connect(2) に指定されたリモートアドレスのパス名が存在しなかった。

       ENOMEM メモリーが足りない。

       ENOTCONN
              ソケット操作にターゲットアドレスが必要だが、 このソケットは接続されていない。

       EOPNOTSUPP
              ストリーム指向でないソケットに対してストリーム操作が呼び出された。 または帯域外デー
              タオプションを用いようとした。

       EPERM  送信者が struct ucred に不正な信任状を渡した。

       EPIPE  リモートソケットがストリームソケット上でクローズされた。 可能な場合は SIGPIPE  も同
              時に送られる。これを避けるには  MSG_NOSIGNAL  フラグを send(2)  や sendmsg(2)  に渡
              す。

       EPROTONOSUPPORT
              渡されたプロトコルが AF_UNIX でない。

       EPROTOTYPE
              リモートソケットとローカルソケットのタイプが一致していなかった    (SOCK_DGRAMSOCK_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
              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.

       他にも汎用のソケット層でエラーが起こったり、  ファイルシステム上にソケットオブジェクトを作
       ろうとした場合に ファイルシステムのエラーが起こることがある。  それぞれの詳細は適切な  man
       ページを参照すること。

バージョン

       SCM_CREDENTIALS  と抽象名前空間は、Linux 2.2 で導入された。 移植性が必要なプログラムでは使
       うべきではない。 (BSD 由来のシステムの中にも信任状の送受信をサポートしているものがあるが、
       その実装の詳細はシステムによって異なる)

注意

       ファイル名を指定してソケットにバインドすると、ファイルシステムにソケットが  生成される。こ
       れは必要なくなったときに呼びだしたユーザーが削除しなければ ならない (unlink(2) を用いる)。
       UNIX で通常使われる「背後で閉じる方式」 が適用される。ソケットはいつでも unlink することが
       でき、最後の参照が クローズされたときにファイルシステムから削除される。

       SOCK_STREAM  ソケット上でファイルディスクリプターや信任状を渡すためには、同じ   sendmsg(2)
       や  recvmsg(2)  コールで補助データ以外のデータを少なくとも 1 バイト送信/受信しなければなら
       ない。

       UNIX ドメインのストリームソケットでは、 帯域外データの概念はサポートされない。

バグ

       ソケットをアドレスに結びつける際、 Linux は終端の NULL が sun_path  になかった場合に追加す
       る実装の一つである。  ほとんどの場合、 これは問題にならない。 ソケットアドレスが取得された
       際、ソケットをバインドしたときに指定したものより 1  バイト長くなるだけである。  しかしなが
       ら、紛らわしい動作が起こる場合が一つある。 ソケットをバインドした際に 108 個の NULL でない
       バイトを指定した場合、 終端の NULL が追加されるとパス名の長さが sizeof(sun_path)  を超えて
       しまう。 結果として、(例えば accept(2) で) ソケットアドレスを取得した際に、 値を取得する呼
       び出しの入力の address 引数に sizeof(struct sockaddr_un) を指定したとすると、 返されるアド
       レス構造体は sun_path に終端の NULL を「含まない」ことになる。

       さらに、 いくつかの実装では、ソケットをバインドする際に終端の NULL が必要ではなく (addrlen
       引数を使って sun_path の長さが判定される)、 このような実装でソケットアドレスを取得する際に
       は、 sun_path に終端の NULL は存在しない。

       ソケットアドレスを取得するアプリケーションでは、 sun_path に終端の NULL が存在しないという
       移植性の問題を、  パス名の有効なバイト数が以下のようになると事実を考慮することで取り扱うこ
       とができる。

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

       他の方法としては、 アプリケーションがソケットアドレスを取得する際、 取得の呼び出しを行う前
       に、 大きさが sizeof(struct sockaddr_un)+1 のバッファーを割り当てることもできる。 取得の呼
       び出しでは  addrlensizeof(struct sockaddr_un) を指定すると、 余分な一つの 0 バイトによ
       り sun_path で返される文字列に終端の NULL が含まれることが保証される。

           void *addrp;

           addrlen = sizeof(struct sockaddr_un);
           addrp = malloc(addrlen + 1);
           if (addrp == NULL)
               /* Handle error */ ;
           memset(addrp, 0, addrlen + 1);

           if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == -1)
               /* handle error */ ;

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

       アプリケーションが「パス名ソケット」の節で説明したルールにしたがってパス名を「作成」してい
       れば、 このような分かりにくさは避けることができる。

       The following code demonstrates the use of sequenced-packet sockets for local interprocess
       communication.  It consists of two programs.  The server program waits  for  a  connection
       from  the client program.  The client sends each of its command-line arguments in separate
       messages.  The server treats the incoming messages as integers  and  adds  them  up.   The
       client sends the command string "END".  The server sends back a message containing the sum
       of the client's integers.  The client prints the sum and exits.  The server waits for  the
       next  client  to  connect.  To stop the server, the client is called with the command-line
       argument "DOWN".

       The following output  was  recorded  while  running  the  server  in  the  background  and
       repeatedly  executing  the  client.  Execution of the server program ends when it receives
       the "DOWN" command.

   出力例
           $ ./server &
           [1] 25887
           $ ./client 3 4
           Result = 7
           $ ./client 11 -5
           Result = 6
           $ ./client DOWN
           Result = 0
           [1]+  Done                    ./server
           $

   プログラムのソース

       /*
        * File connection.h
        */

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

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

           /* Create local socket. */

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

           /*
            * For portability clear the whole structure, since some
            * implementations have additional (nonstandard) fields in
            * the structure.
            */

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

           /* Bind socket to socket 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);
           }

           /*
            * Prepare for accepting connections. The backlog size is set
            * to 20. So while one request is being processed other requests
            * can be waiting.
            */

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

           /* This is the main loop for handling connections. */

           for (;;) {

               /* Wait for incoming connection. */

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

               result = 0;
               for (;;) {

                   /* Wait for next data packet. */

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

                   /* Ensure buffer is 0-terminated. */

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

                   /* Handle commands. */

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

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

                   /* Add received summand. */

                   result += atoi(buffer);
               }

               /* Send result. */

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

               /* Close socket. */

               close(data_socket);

               /* Quit on DOWN command. */

               if (down_flag) {
                   break;
               }
           }

           close(connection_socket);

           /* Unlink the socket. */

           unlink(SOCKET_NAME);

           exit(EXIT_SUCCESS);
       }

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

           /* Create local socket. */

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

           /*
            * For portability clear the whole structure, since some
            * implementations have additional (nonstandard) fields in
            * the structure.
            */

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

           /* Send arguments. */

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

           /* Request result. */

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

           /* Receive result. */

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

           /* Ensure buffer is 0-terminated. */

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

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

           /* Close socket. */

           close(data_socket);

           exit(EXIT_SUCCESS);
       }

       SCM_RIGHTS の使用例については cmsg(3) を参照。

関連項目

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

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。