/***************************************/
/*            - TCP server -           */
/***************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h> 

#define BUFSIZE 1024                      // buffer size
#define PORT_NO 2001                      // port number
#define error(a,b) fprintf(stderr, a, b)  // error 'function'

int main(int argc, char *argv[] ){ // arg count, arg vector 

   /************************** Declarations ***********************/
   int fd;	        	           // socket endpoint
   int fdc;                        // socket endpoint
   int flags;                      // receive/send flags
   struct sockaddr_in server;      // address of server
   struct sockaddr_in client;      // address of client
   unsigned int server_size;       // length of the sockaddr_in server
   unsigned int client_size;       // length of the sockaddr_in client
   int bytes;                      // length of buffer 
   int rcvsize;                    // received bytes
   int trnmsize;                   // transmitted bytes
   int err;                        // error code
   char on;                        // sockopt option
   char buffer[BUFSIZE+1];         // datagram dat buffer area   

   /********************** Initialization *************************/
   on                     = 1;
   flags                  = 0;
   bytes                  = BUFSIZE;
   server.sin_family      = AF_INET;
   server.sin_addr.s_addr = INADDR_ANY;
   server.sin_port        = htons(PORT_NO);
   server_size            = sizeof server;
   client_size            = sizeof client;

   /************************ Creating socket **********************/
   fd = socket(AF_INET, SOCK_STREAM, 0 );
   if ( fd < 0 ) {
      error("%s: Socket creation error\n",argv[0]);
      exit(1);
      }

   /************************ Setting options **********************/
   setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
   setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);

   /************************ Binding socket ***********************/
   err = bind( fd, (struct sockaddr *) &server, server_size);
   if ( err < 0 ) {
      error("%s: Cannot bind to the socket\n",argv[0]);
      exit(2);
      }

   /************************ Listening ****************************/
   err = listen( fd, 10);
   if ( err < 0 ) {
      error("%s: Cannot listen to the socket\n",argv[0]);
      exit(3);
      }

   /************************ Accepting data ***********************/
   fdc = accept( fd, (struct sockaddr *) &client, &client_size);
   if ( fdc < 0 ) {
      error("%s: Cannot accept on socket\n",argv[0]);
      exit(4);
      }

   /************************ Receiving from the client ************/
   rcvsize = recv( fdc, buffer, bytes, flags );
   if ( rcvsize < 0 ) {
      error("%s: Cannot receive from the socket\n",argv[0]);
      exit(5);
      }

   /************************ User interface ***********************/
   printf (" %i bytes have been received from client.\n Message: %s \n", 
           rcvsize-1, buffer);

   /************************ Sending acknowledgement *****************/
   sprintf(buffer,"Transmit is OK.");
   bytes = strlen(buffer) + 1;
   trnmsize = send( fdc, buffer, bytes, flags );
   if ( trnmsize < 0 ) {
      error("%s: Cannot send to server\n",argv[0]);
      exit(6);
      }

   /********************** User interface ************************/
   printf (" Acknowledgement has been sent to client.\n");

   close(fd);
   close(fdc);
   exit(0);
   } 
