ptg10805159
Section 16.5 Data Transfer 617
To find its address, the server needs to get the name of the host on which it is
running. If the maximum host name length is indeterminate, we useHOST_NAME_MAX
instead. If the system doesn’t defineHOST_NAME_MAX, we define it ourselves. POSIX.1
requires the maximum host name length to be at least 255 bytes, not including the
terminating null, so we defineHOST_NAME_MAXto be 256 to include the terminating
null.
The server gets the host name by callinggethostnameand looks up the address
for the remote uptime service. Multiple addresses can be returned, but we simply
choose the first one for which we can establish a passive socket endpoint (i.e., one used
only to listen for connect requests). Handling multiple addresses is left as an exercise.
We use theinitserverfunction from Figure16.12 to initialize the socket endpoint
on which we will wait for connect requests to arrive. (Actually, we use the version from
Figure16.22; we’ll see why when we discuss socket options in Section 16.6.)
Example — Alternative Connection-Oriented Server
Previously, we stated that using file descriptors to access sockets was significant,
because it allowed programs that knew nothing about networking to be used in a
networked environment. The version of the server shown in Figure16.18 illustrates this
point. Instead of reading the output of theuptimecommand and sending it to the
client, the server arranges to have the standardoutput and standarderror of the
uptimecommand be the socket endpoint connected to the client.
#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define QLEN 10
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif
extern int initserver(int, const struct sockaddr *, socklen_t, int);
void
serve(int sockfd)
{
int clfd, status;
pid_t pid;
set_cloexec(sockfd);
for (;;) {
if ((clfd = accept(sockfd, NULL, NULL)) < 0) {
syslog(LOG_ERR, "ruptimed: accept error: %s",
strerror(errno));