编程接口指南

inetd 守护进程

inetd(1M) 守护进程在启动时调用,并从 /etc/inet/inetd.conf 文件中获取此守护进程侦听的服务。此守护进程针对 /etc/inet/inetd.conf 中列出的每个服务创建一个套接字,将相应的端口号绑定到每个套接字。有关详细信息,请参见 inetd(1M) 手册页。

inetd(1M) 守护进程轮询每个套接字,等待向对应于此套接字的服务发出连接请求。对于 SOCK_STREAM 类型套接字,inetd(1M) 在侦听套接字时接受 (accept(3SOCKET)),派生 (fork(2)),将新套接字复制 (dup(2)) 到文件描述符 01stdinstdout),关闭其他开放式文件描述符,并执行 (exec(2)) 相应服务器。

使用 inetd(1M) 的主要优点就是未使用的服务不占用计算机资源。次要优点是 inetd(1M) 会尽力建立连接。在文件描述符 01 中,由 inetd(1M) 启动的服务器的套接字连接至其客户机。服务器可以立即进行读取、写入、发送或接收。只要服务器在适当的时候使用 fflush(3C),便可以使用 stdio 约定所提供的缓冲 I/O。

getpeername(3SOCKET) 例程将返回连接到套接字的对等方(进程)的地址。此例程在由 inetd(1M) 启动的服务器中非常有用。例如,可以使用此例程记录诸如 fec0::56:a00:20ff:fe7d:3dd2(通常用于表示客户机的 IPv6 地址)的 Internet 地址。inetd(1M) 服务器可以使用以下样例代码:

    struct sockaddr_storage name;

    int namelen = sizeof (name);

    char abuf[INET6_ADDRSTRLEN];

    struct in6_addr addr6;

    struct in_addr addr;



    if (getpeername(fd, (struct sockaddr *)&name, &namelen) == -1) {

        perror("getpeername");

        exit(1);

    } else {

        addr = ((struct sockaddr_in *)&name)->sin_addr;

        addr6 = ((struct sockaddr_in6 *)&name)->sin6_addr;

        if (name.ss_family == AF_INET) {

                (void) inet_ntop(AF_INET, &addr, abuf, sizeof (abuf));

        } else if (name.ss_family == AF_INET6 &&

                   IN6_IS_ADDR_V4MAPPED(&addr6)) {

                /* this is a IPv4-mapped IPv6 address */

                IN6_MAPPED_TO_IN(&addr6, &addr);

                (void) inet_ntop(AF_INET, &addr, abuf, sizeof (abuf));

        } else if (name.ss_family == AF_INET6) {

                (void) inet_ntop(AF_INET6, &addr6, abuf, sizeof (abuf));



        }

        syslog("Connection from %s\n", abuf);

    }