DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
Developing applications over TCP/IP using Internet sockets

Server processes without connections (Internet domain)

While connection-based services are the norm, some services are based on the use of datagram sockets. The rwho(TC) service provides users with status information for hosts connected to a local area network. This service, while predicated on the ability to broadcast information to all hosts connected to a particular network, is of interest as an example usage of datagram sockets.

A user on any machine running the rwho server may find out the current status of a machine with the ruptime(TC) program. The output is similar to:

   laibbb      up 21:56
   laibel      up 21:54
   laiden      up 18:31
   laidy       up 19:29
Status information for each host is periodically broadcast by rwho server processes on each machine. The same server process also receives the status information and uses it to update a database. This database is then interpreted to generate the status information for each host. Servers operate autonomously, coupled only by the local network and its broadcast capabilities.

The rwho server performs two separate tasks, as shown in ``Sample rwho server''. The first task is to act as a receiver of status information broadcast by other hosts on the network. This job is carried out in the main loop of the program. Packets received at the rwho port are interrogated to ensure that they have been sent by another rwho server process, then are time stamped with their arrival time and used to update a file indicating the status of the host. When a host has not been heard from for an extended period of time, the database interpretation routines assume the host is down and indicates such on the status reports. This algorithm is prone to error because a server may be down while a host is actually up, but it works well in a LAN.

Sample rwho server

main()
{
  /* ... */
  sp = getservbyname("who", "udp");
  net = getnetbyname("localnet");
  sin.sin_addr = inet_makeaddr(net->n_net, INADDR_ANY);
  sin.sin_port = sp->s_port;
  /* ... */
  s = socket(AF_INET, SOCK_DGRAM, 0);
  /* ... */
  bind(s, (struct sockaddr *) &sin, sizeof (sin));
  /* ... */
  signal(SIGALRM, onalrm);
  onalrm();
  for (;;) {
     struct whod wd;
     int cc, whod, len = sizeof (from);
     cc=recvfrom(s,(char*)&wd,sizeof(structwhod),0,&from,&len);
     if (cc <= 0) {
        if (cc < 0 && errno != EINTR)
           perror("rwhod: recv");
        continue;
     }
     if (from.sin_port != sp->s_port) {
        fprintf(stderr, "rwhod: %d: bad from port\n",
                ntohs(from.sin_port));
        continue;
     }
     /* ... */
     if (!verify(wd.wd_hostname)) {
         fprintf(stderr,"rwhod:malformedhostnamefrom%x\n",
                 ntohl(from.sin_addr.s_addr));
         continue;
     }
     (void)sprintf(path,"%s/whod.%s",RWHODIR,wd.wd_hostname);
     whod = open(path, O_WRONLY|O_CREATE|O_TRUNCATE, 0666);
     /* ... */
     (void) time(&wd.wd_recvtime);
     (void) write(whod, (char *)&wd, cc);
     (void) close(whod);
  }
}
The second task performed by the server is to supply information regarding the status of its host. This involves periodically acquiring system status information, packaging it up in a message, and broadcasting it on the local network for other rwho servers to hear. The supply function is triggered by a timer and runs off a signal. Locating the system status information is somewhat involved, but not overly creative. However, deciding where to transmit the resultant packet does indicate some problems with the current protocol.

Status information is broadcast on the local network. For networks which do not support broadcasting, another method must be used to simulate or replace it. One possibility is to enumerate the known neighbors (based on the status received). This, unfortunately, requires some bootstrapping information, because a server started up on a quiet network will have no known neighbors and thus never receive or send any status information. This same problem affects the routing table management process in propagating routing status information.

The standard solution, unsatisfactory as it may be, is to inform one or more servers of their known neighbors and request that they always communicate with these neighbors. If each server has at least one neighbor supplied to it, status information can then propagate through a neighbor to hosts which cannot possibly be direct neighbors. If the server supports networks which provide a broadcast capability, as well as those which do not, then networks with an arbitrary topology can share status information. (However, if a host is connected to multiple networks, it may receive status information from itself. This can lead to an endless loop of information.)

The second problem with the current scheme is that the rwho process services only a single local network, and this network is found by reading a file. It is important that software operating in a distributed environment not have any site-dependent information compiled into it. This would require a separate copy of the server at each host and make maintenance a problem. System calls are provided to assist developers in isolating host-specific information from the application code. One example of such a system call is gethostname(SLIB), which returns the ``official'' name of the host.


Next topic: IPC programming techniques (Internet domain)
Previous topic: Client processes (Internet domain)

© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003