/* Author: Pete Broadwell, Grinnell College
   Minor Adjustments for Linux made 11/29/00 by Henry M. Walker

   This program uses datagram sockets to simulate a simple scenario of the
   readers-writers program. The writer (server) process reads the reader
   (client)'s greeting from the socket and then writes 10 integers to the
   socket. The client process, in an unconnected state, reads these integers.

*/

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>   /* socket command libraries needed by some compilers */
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>

#define SIM_LENGTH 9 /* number of integers to be written and read */
#define PORT 1228 /* local port on which connection will be established */

/* procedure to remove socket file and exit */
void clean_up(int cond, int *sock)
{ printf("Exiting now.\n");
  close(*sock);
  exit(cond);
} /* end of clean_up */

int main(void)
{ pid_t pid;

  pid = fork();     /* spawn new child process */
  if (-1 == pid)
    { perror ("Error in fork");
      exit(1);
    }

  if (0 == pid)
    { /* processing for client */
      int sock; 
      struct sockaddr_in cli_name;
      int value; /* variable for number read from socket */
      size_t len; /* variable for size of cli_name structure */
      int count;
      char msg[20]; /* array for message to be written to socket */


      /* set the socket descriptor */
      sock = socket(AF_INET, SOCK_DGRAM, 0);
      if (sock < 0)
        { perror("Error opening channel");
          clean_up(1, &sock);
        }

      /* set the physical address (cli_name) of the socket descriptor */
      bzero(&cli_name, sizeof(cli_name));
      cli_name.sin_family = AF_INET;
      cli_name.sin_port = htons(PORT);

      sleep(1); /* give server time to create socket */
      printf("Client is alive.\n");

      /* initialize the msg array */
      for (count = 0; count++; count < 20)
        msg[count] = 0;

      /* write greeting to the socket */
      len = sizeof(cli_name);
      strcpy(msg, "Hello, server");
      sendto(sock, &msg, strlen(msg), 0, (struct sockaddr *)&cli_name, len);
      printf("Client has sent  %s  to socket.\n", msg);

      /* read greeting from the server */
      recvfrom(sock, &msg, 20, 0, (struct sockaddr *)&cli_name, &len);
      printf("Client has received  %s  from socket.\n", msg);

      /* read integers from the socket */
      for (count = 0; count < SIM_LENGTH; count++)
        { recvfrom(sock, &value, 4, 0, (struct sockaddr *)&cli_name, &len);
          printf("Client has received %d from socket.\n", value);
        }

      close(sock); /* close connection to socket */
      exit(0);

    } /* end of processing for client */

  else
    { /* processing for server */
      int sock;
      struct sockaddr_in serv_name;
      int count;
      char msg[20]; /* array for greeting to be read from socket */
      size_t len; /* variable for size of name structure */

      /* set socket descriptor */
      sock = socket(AF_INET, SOCK_DGRAM, 0);
      if (sock < 0)
        { perror("Error opening channel");
          clean_up(1, &sock);
        }



      /* set the physical address (serv_name) of the socket descriptor */
      bzero(&serv_name, sizeof(serv_name));
      serv_name.sin_family = AF_INET;
      serv_name.sin_port = htons(PORT);

      /* bind the socket address to the socket descriptor */
      if (bind(sock, (struct sockaddr *)&serv_name, sizeof(serv_name)) < 0)
        { perror("Error naming channel");
          clean_up(1, &sock);
        }

      printf("Server is on line.\n");

      for (count = 0; count++; count < 20)
        msg[count] = 0;

      /* read greeting from client */
      len = sizeof(serv_name);
      recvfrom(sock, &msg, 20, 0, (struct sockaddr *)&serv_name, &len);
      printf("Server has read  %s  from socket.\n", msg);

      strcpy(msg, "Hello, client");

      /* write reply to client */
      sendto(sock, &msg, strlen(msg), 0, (struct sockaddr *)&serv_name, len);

      printf("Server has written  %s  to socket.\n", msg);

      /* write integers to socket */
      for (count = 1; count <= SIM_LENGTH; count++)
        { sendto(sock, &count, 4, 0, (struct sockaddr *)&serv_name, len);
          printf("Server has written %d to socket.\n", count);
        }

      waitpid(pid, NULL, 0); /* Wait for client process to terminate */
      clean_up(0, &sock); /* Exit with no errors */
    } /* end of processing for server */

} /* end of main */
