/* client.c - code for example client program using TCP 
 *            From "Computer Networks and Internets" by 
 *            D.Comer
 *            Modified by G.Ingargiola to make sure that ports are
 *            immediately reusable (Unix only).
 */

#ifndef unix
#define WIN32
#include <windows.h>
#include <winsock.h>
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif

#include <stdio.h>
#include <string.h>

#define PROTOPORT 5194 /*default protocol port number*/
extern int errno;
char localhost[] = "localhost"; /*default host name */
/****************************************************************
 * Program: client
 * Purpose: Allocate a socket, connect to a server, and print all output
 * Syntax: client [host [port]]
 *                 host: name of computer on which server is executing
 *                 port:protocol port number server is using
 * Note: Both arguments are optional. If no host name is specified
 *       the client uses "localhost"; if no protocol port is
 *       specified, the client uses the default given by PROTOPORT.
 ****************************************************************/

main(argc, argv)
int argc;
char *argv[];
{
	struct hostent *ptrh;  /* pointer to a host table entry     */
	struct protoent *ptrp; /* pointer to a protocol table entry */
	struct sockaddr_in sad;/* structure to hold server's address*/
	int    sd;             /* socket descriptor                 */
	int    port;           /* protocol port number              */
	char   *host;          /* pointer to host name              */
	int    n;              /* number of characters read         */
	char   buf[1000];      /* buffer for data from the server   */
	int    option_value;   /* GPI: needed for setsockopt        */
#ifdef WIN32
	WSADATA wsaData;
	WSAStartup(0x0101, &wsaData);
#endif
	memset((char *)&sad, 0, sizeof(sad)); /* clear sockaddr structure */
	sad.sin_family = AF_INET;  /* set family to Internet */

	/* Check command-line argument for protocol port and extract
	 * port number if one is specified. Otherwise, use the default
	 * port value given by constant PROTOPORT
	 */
	if (argc > 2) {         /* If protocol port is specified */
       port = atoi(argv[2]);/* Convert to binary */
	} else {
	   port = PROTOPORT;    /* use default port number */
	}
	if (port > 0)           /* Test for legal value */
		sad.sin_port = htons((u_short)port);
	else {                  /* Print error message and exit */
		fprintf(stderr,"bad port number %s\n", argv[2]);
		exit(1);
	}

	/* Check host argument and assign host name */
	if (argc > 1) {
		host = argv[1];     /* If host argument is specified */
	} else {
		host = localhost;
	}

	/* Convert host name to equivalent IP address and copy sad */
	ptrh = gethostbyname(host);
	if (((char *)ptrh) == NULL) {
		fprintf(stderr, "invalid host: %s\n", host);
		exit(1);
	}
	memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);

	/* Map TCP tranbsport protocol name to protocol number */
	if (((int)(ptrp = getprotobyname("tcp"))) == 0) {
		fprintf(stderr, "cannot map \"tcp\" to protocol number");
		exit(1);
	}

	/* Create a socket */
	sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
	if (sd < 0) {
		fprintf(stderr, "socket creation failed\n");
		exit(1);
	}

	/* GPI: Make sure that port used will be immediately reusable */
	option_value = 1;
	if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, 
			     (char *)&option_value, sizeof(option_value)) < 0)
	  {
	        perror("setsockopt");
		exit(1);
	  }

	/* Connect the socket to the specified server */
	if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
		fprintf(stderr, "connect failed\n");
		exit(1);
	}

	/* Repeatedly read data from socket and write to user's screen */
	n = recv(sd, buf, sizeof(buf), 0);
	while (n>0) {
		write(1, buf, n);
		n = recv(sd, buf, sizeof(buf), 0);
	}

	/* Close socket */
	closesocket(sd);
	unlink(sd);

	/* Terminate client program gracefully */
	exit(0);

}





