/* COMPILE:     gcc server.c -o server -lsocket -lnsl
		gcc client.c -o client -lsocket -lnsl
   NOTE:  -lsocket -lnsl  needed on SOLARIS, but can be omitted for other UNIX.
       RUN:     server 5100 &
		client localhost 5100
   (or accept default PORTNUM)
*/

#ifndef DATAGRAM
#define STREAM  /* default service (tcp protocol) */
#endif

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>

#define PORTNUM 5100 /* replace by yours -- this is public part of protocol */

main(int argc, char ** argv)
{
  int main_socket, new_socket;
  char server_name[256]; /* holds local server's host name */
  struct hostent *server_ent; /* holds return value of gethostbyname() */
  struct sockaddr_in server_addr;
  struct sockaddr_in client_addr;
  int client_addr_len;
#ifdef DATAGRAM
  int msglen;
#endif
  struct timezone time_zone;
  struct timeval time_val;
  long time;
  char buffer[256];
  int portnum;

  alarm(3600); /* Causes process to kill itself after 3600 sec (1 hour) */

  portnum = ( argc == 2 ? atoi(argv[1]) : PORTNUM );

  /* create public socket for listening */
#ifdef STREAM
  main_socket = socket(AF_INET, SOCK_STREAM, 0);
#else
  main_socket = socket(AF_INET, SOCK_DGRAM, 0);
#endif

  /* Construct server address.  This has three parts:
       protocol family, server internet address, and port number */
  /* VERY IMPORTANT:  zero out ALL fields of server_addr before using it */
  bzero((char *)&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  /* Accept connection on any ethernet port of local host: */
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(portnum); /* htons for CPU-indep byte order */

  /* bind server socket to local server address (which includes port) */
  if (bind(main_socket, (struct sockaddr *)&server_addr, sizeof(server_addr))
      == -1) {
    perror("server(bind)");
    exit();
  }

#ifdef STREAM
  listen(main_socket, 5);  /* number of pending client requests allowed;
			 OS currently supports a maximum of 5 */
#endif

  while(1){
    client_addr_len = sizeof(client_addr);
#ifdef STREAM
    /* accept creates a new socket for each client -- perfect for servers
       It also fills in the variable's client_addr and client_addr_len */
    new_socket = accept( main_socket, (struct sockaddr *)&client_addr,
			 &client_addr_len );
#else
    msglen = recvfrom(main_socket, buffer, sizeof(buffer), 0,
		       &client_addr, &client_addr_len);
    if(msglen == -1) {
      perror("server(recvfrom)");
      exit();
    }
#endif

    /* Some servers would choose to fork a child and continue within child,
       so that parent can go on to process other requests.  Since fulfilling
       the request is quick, we don't bother here. */
    gettimeofday(&time_val, &time_zone);
    time = time_val.tv_sec;
    time = htonl(time); /* convert to network byte order (CPU-independent) */
#ifdef STREAM
    write(new_socket, (char *)&time, sizeof(time));
#else
    sendto(main_socket, (char *)&time, sizeof(time), 0,
	   &client_addr, sizeof(client_addr));
#endif
    close(new_socket);
  }

  exit(0);
}

