The Socket Interface Connectionless Mode Service

 
 
        o Routines for connectionless mode:
 
            -- sendto( )
                  o Sends a data unit to a specified address
 
            -- recvfrom( )
                  o Receives a data unit
                  o Obtains address of sender
 

General Flow

 
 
                   Server
                  socket( )
                     |
                     |                                 Client
                     |
                   bind( )
                     |
                     |                                 socket( )
                     |                                     |
                                                           |
                 recvfrom( )                               |
                     |
                     |                                  bind( )
                     |                                     |
        blocks until data received                         |
                from client                                |
                     +++++ ++++++++++++++++++++++++   sendto( )
                     |
                     |                                     |
                                                           |
                                                           |
                  sendto( )    +++++++                     |
                                      ++++++++
                                              ++++
                                                      recvfrom( )
 

Server Code

 
          #include <stdio.h>
          #include <sys/types.h>
          #include <sys/socket.h>
          #include <netinet/in.h>
 
          #define SERV_PORT  5134
          #define MAXNAME    1024
 
          main()
          {
               int dg_fd;                 /* file descriptor into UDP    */
               struct sockaddr_in myaddr; /* the address of this service */
               int len;                   /* length of address           */
               char buff[MAXNAME];        /* buffer to hold datagram     */
               char reply;                /* the response to the client  */
               struct sockaddr_in client_addr; /* the address of client  */
 
               char cmd[BUFSIZ];           /* used to figure out if the  */
               char junkbuf[BUFSIZ];       /* specified user is logged   */
               FILE *fp;                   /* onto the system            */
 
               /* Open a socket into UDP/IP */
               if ((dg_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                    perror("socket failed");
                    exit(1);
               }
 
               /* Set up our address */
               bzero((char *)&myaddr, sizeof(myaddr));
               myaddr.sin_family = AF_INET;
               myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
               myaddr.sin_port = htons(SERV_PORT);
         
               /* Bind to the address of this service */
               if (bind(dg_fd, (struct sockaddr *)&myaddr,
                                 sizeof(myaddr)) < 0) {
                    perror("bind failed");
                    exit(1);
               }
 
               /* Loop continuously, processing datagrams */
               len = sizeof(struct sockaddr);
 
               while (1) {
                    if (recvfrom(dg_fd, buff, MAXNAME, 0,
                               &client_addr, &len) < 0) {
                         perror("could not read datagram!");
                         continue;
                    }
 
                    sprintf(cmd, "who | grep '^%s '", buff);
                    if ((fp = popen(cmd, "r")) == NULL
                              || fgets(junkbuf, BUFSIZ, fp) == NULL) {
                         reply = 'n';
                    } else {
                         reply = 'y';
                    }
 
                    if (sendto(dg_fd, &reply, 1, 0, &client_addr, len) < 0) {
                         perror("could not send datagram!");
                         continue;
                    }
               }
          }
 

Notes

 
 
        o The fourth argument of recvfrom( ) and sendto( ) is a flags
          field
            -- You can set flags that specify out-of-band data
 
        o The recvfrom( ) routine fills in the address of the sender
         

Client Code

 
 
          #include <stdio.h>
          #include <netdb.h>
          #include <signal.h>
          #include <sys/types.h>
          #include <sys/socket.h>
          #include <netinet/in.h>
 
          #define SERV_PORT  5134
          #define MAXNAME    1024
          #define NUM_TRIES   20
 
          int timed_out;
          main(argc, argv)
          int argc;
          char **argv;
          {
               int fd;                   /* fd into transport provider */
               char buf[MAXNAME];        /* holds message from server  */
               int tries = NUM_TRIES;    /* number of tries to send    */
               int got_it = 0;           /* determines datagram receipt*/
               struct hostent *hp;       /* holds address of server    */
               struct sockaddr_in myaddr; /* holds the local address   */
               struct sockaddr_in servaddr; /* holds the server address*/
               int length;               /* length of user name        */
               int size;                 /* size of sockaddr structure */
               void handler();           /* handles timeout signals    */
 
               /*
                *  Check for proper usage
                */
 
               if (argc != 3) {
                    fprintf(stderr,"Usage: %s user server\n", argv[0]);
                    exit(2);
               }
         
               /*
                *  Open the socket into UDP/IP
                */
 
               if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                    perror("socket failed!");
                    exit(1);
               }
 
               /*
                *  Bind to an arbitrary return address
                */
 
               bzero((char *)&myaddr, sizeof(myaddr));
               myaddr.sin_family = AF_INET;
               myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
               myaddr.sin_port = htons(0);
 
               if (bind(fd, (struct sockaddr *)&myaddr,
                                          sizeof(myaddr)) < 0) {
                    perror("bind failed!");
                    exit(1);
               }
 
               /*
                *  Fill in the server's UDP/IP address
                */
 
               bzero((char *)&servaddr, sizeof(servaddr));
               servaddr.sin_family = AF_INET;
               servaddr.sin_port = htons(SERV_PORT);
               hp = gethostbyname(argv[2]);
 
               if (hp == 0) {
                    fprintf(stderr,
                        "could not obtain address of %s\n", argv[2]);
                    exit(1);
               }
 
               bcopy(hp->h_addr_list[0], (caddr_t)&servaddr.sin_addr,
                    hp->h_length);
               length = strlen(argv[1]);
               size = sizeof(servaddr);
 
               while (tries --) {
                    if (sendto(fd, argv[1], length, 0,
                        (struct sockaddr *)&servaddr, size) != length) {
                         perror("sendto failed!\n");
                         exit(1);
                    }
                    /*
                     *   Allow 15 seconds for the response to arrive
                     */
                    timed_out = 0;
                    signal(SIGALRM, handler);
                    alarm(15);
                    if (recvfrom(fd, buf, MAXNAME, 0,
                                (struct sockaddr *)0, (int *)0) >= 0) {
                         alarm(0);
                         got_it = 1;
                         break;
                    }
                    if (timed_out) {
                         continue;
                    }
                    fprintf(stderr, "recvfrom failed!\n");
                    exit(1);
               }
         
               if (!got_it) {
                    printf("failed %d times, exiting\n", NUM_TRIES);
                    exit(1);
               }
 
               if (buf[0] == 'y') {
                    printf("%s is logged on server\n", argv[1]);
               } else {
                    printf("%s is not logged on server\n", argv[1]);
               }
               exit(0);
          }
 
          void
          handler()
          {
               timed_out = 1;
          }