HPlogo HP 9000 Networking: BSD Sockets Interface Programmer's Guide > Chapter 8 Programming Hints

Adding a Server Process to the Internet Daemon

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Glossary

 » Index

This section contains example BSD Sockets programs that use the internet daemon, called inetd. For more information on inetd, refer to the inetd(1M) man page.

You can invoke the example server programs from inetd if you have super-user capabilities and you make the following configuration modifications:

  • Add the following lines to the /etc/inetd.conf file:

    example  stream  tcp  nowait  root  <path>/server.tcp  server.tcp
    example dgram udp wait root <path>/server.udp server.udp

    where <path> is the path to the files on your host.

  • Add the following lines to the /etc/services file:

    example 22375/tcp
    example 22375/udp
  • If inetd is already running, execute the following command so that inetd recognizes the changes:

    /etc/inetd -c

These example programs do the same thing as the previous example servers do, but they are designed to be called from inetd. They do not have daemon loops or listen for incoming connection requests, because inetd does that. The source code for the two example servers follows.

/*
* S E R V E R . T C P
*
* This is a variation of the example program called serv.tcp.
* This one performs the same function, except that it is
* designed to be called from /etc/inetd. This version does
* not contain a daemon loop, and does not listen for incoming
* connections on the socket. /etc/inetd does these functions.
* This server simply assumes that the socket to receive the
* messages from and send the responses to is file descriptor
* 0 when the program is started. It also assumes that
* the client connection is already established to the socket.
* For the sake of simplicity, the activity logging
* functions of serv.tcp have also been removed.
*
*/

/*
* M A I N
*
* This is the actual server routine that the /etc/inetd forks to
* handle each individual connection. Its purpose is to receive
* the request packets from the remote client, process them,
* and return the results to the client.
*
*/
main()
{
char buf[10]; /* This example uses 10 byte messages. */
int len, lenl;

/* Go into a loop, receiving requests from the remote
* client. After the client has sent the last request,
* it will do a shutdown for sending, which will cause
* an end-of-file condition to appear on this end of the
* connection. After all the client's requests have
* been received, the next recv call will return zero
* bytes, signaling an end-of-file condition. This is
* how the server will know that no more requests will
* follow, and the loop will be exited.
*/
while (len = recv(0, buf, 10, 0)) {
if (len == -1) {
exit (1); /* error from recv */
}
/* The reason this while loop exists is that there
* is a remote possibility of the above recv returning
* less than 10 bytes. This is because a recv returns
* as soon as there is some data, and will not wait for
* all of the requested data to arrive. Since 10 bytes
* is relatively small compared to the allowed TCP
* packet sizes, a partial receive is unlikely. If
* this example had used 2048 bytes requests instead,
* a partial receive would be far more likely.
* This loop will keep receiving until all 10 bytes
* have been received, thus guaranteeing that the
* next recv at the top of the loop will start at the
* beginning of the next request.
*/
while (len < 10) {
len1 = recv(0, &buf[len], 10-len, 0);
if (len1 == -1) {
exit (1);
}
len += len1;
}
/* This sleep simulates the processing of
* the request that a real server may do.
*/
sleep(1);
/* Send a response back to the client. */
if (send(0, buf, 10, 0) != 10) {
exit (1);
}
}
}
/* The loop has terminated, because there are no
* more requests to be serviced.
exit (0);
}
/*
* S E R V E R . U D P
*
* This is a variation of the example program called serv.udp.
* This one performs the same function, except that it is
* designed to be called from /etc/inetd. This version does
* not contain a daemon loop, and does not wait for requests
* to arrive on a socket. /etc/inetd does these functions. The
* server simply assumes the socket to receive the message
* from and send the response to is file descriptor 0 when
* the program is started. It also assumes that the client's
* request is already ready to be received from the socket.
*
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>

#define BUFFERSIZE 1024 /* max size of packets to be received */
int cc; /* contains the number of bytes read */
char buffer[BUFFERSIZE]; /* buffer for packets to be read into */

struct hostent *hp; /* pointer to info for requested host */

struct sockaddr_in clientaddr_in;/* for client's socket address */
struct in_addr reqaddr; /* for requested host's address */

#define ADDRNOTFOUND 0xffffffff /* return address for unfound
host */

/*
* M A I N
*
* This routine receives the request and returns an answer.
* Each request consists of a host name for which the
* requester desires to know the internet address. The
* server will look up the name in its /etc/hosts file,
* and return the internet address to the client. An
* a internet address value of all ones will be returned
* if the host name is not found.
*
*/
main()
{
int addrlen;

/* clear out address structure */
memset ((char *)&clientaddr_in, 0, sizeof(struct sockaddr_in));

/* Note that addrlen is passed as a pointer
* so that the recvfrom call can return the
* size of the returned address.
*/
addrlen = sizeof(struct sockaddr_in);
/* This call will
* return the address of the client,
* and a buffer containing its request.
* BUFFERSIZE - 1 bytes are read so that
* room is left at the end of the buffer
* for a null character.
*/

cc = recvfrom(0, buffer, BUFFERSIZE - 1, 0 &clientaddr_in,
&addrlen);
if ( cc == -1) exit(1);
/* Make sure the message received in
* null terminated.
*/
buffer[cc]='\0';
/* Treat the message as a string containing
* a hostname. Search for the name
* in /etc/hosts.
*/
hp = gethostbyname (buffer);
if (hp == NULL) {
/* Name was not found. Return a
* special value signifying the error.
/*
reqaddr.s_addr = ADDRNOTFOUND;
} else {
/* Copy address of host into the
* return buffer.
/*
reqaddr.s_addr =
((struct in_addr *)(hp->h_addr))->s_addr;
}
/* send the response back to the requesting client. The
* address is sent in network byte order. Note that
* all errors are ignored. The client
* will retry if it does not receive
* the response.
*/
sendto (0, &reqaddr, sizeof(struct in_addr), 0,
&clientaddr_in, addrlen);
exit(0);
}
© 1997 Hewlett-Packard Development Company, L.P.