/* 
   bind.c
   a sample for bind() that waits for a client to connect.
   you need run bind.c and then, from a seperate terminal, run connect.c.
   These programs must be run together.

   Usage : 
      bind.c [PORT_NUMBER] 
*/

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

#define PROTOPORT 5139 /* default protocol port number */
#define QLEN 6         /* lenght of listenning queue */ 

/* Usage will be display if there is any incorrect option */
char usage[]= "\nThis is a server program that waits for client to connect.\n\nUsage :\n      bind.c [PORT_NUMBER]\n\n      PORT_NUMBER : TCP port number will be used\n\nFor example :\n      bind.c\n      bind.c 6000\n\nThe default optional value :\n      PORT_NUMBER : 5139\n\n";

int main(int argc,char *argv[]) {
    struct protoent *ptrp;  /* pointer to a protocol table entry  */
    struct sockaddr_in sad; /* structure to hold server's address */
    struct sockaddr_in cad; /* structure to hold client's address */
    int    sd,sd2;          /* socket descriptors                 */
    int port;               /* ptotocol prot number               */
    int alen;               /* length of address                  */
    char buf[1000];         /* buffer for string the server sends */

    memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
    sad.sin_family=AF_INET;             /* set family to Internet   */ 
    sad.sin_addr.s_addr=INADDR_ANY;     /* set the local IP address */

    /* get user-defined tcp port number */
    if(argc>1) { 
        port=atoi(argv[1]);   /* convert argument to binary */
    }
    else {
        port=PROTOPORT;       /* use default port number */
    }

    if(port>0)              /* test for illegal value */
        sad.sin_port=htons((u_short)port);
    else {                   /* print erro message and exit */ 
        fprintf(stderr,"\nError : bad port number %s\n",argv[1]);
        printf("%s", usage);
        exit(1);
    }

    /* Map TCP transport protocol name to protocol number */ 
    if(((int)(ptrp=getprotobyname("tcp")))==0) {
        fprintf(stderr,"\nError : cannot map \"tcp\" to protocol number");
        printf("%s", usage);
        exit(1);
    }
    
    /* Creat a socket */
    sd=socket(PF_INET,SOCK_STREAM,ptrp->p_proto);
    if(sd<0) {
        fprintf(stderr,"\nError : socket creation failed \n");
        printf("%s", usage);
        exit(1);
    }
    
    /* Bind a local address to the socket */
    if(bind(sd,(struct sockaddr *)&sad,sizeof(sad))<0) {
        fprintf(stderr,"\nError : bind failed\n");
        printf("%s", usage);
        close(sd);
        exit(1);
    }
    
    /* Specify size of request queue */
    if(listen(sd,QLEN)<0) {
        fprintf(stderr,"listen failed \n");
        close(sd);
        exit(1);
    }
    
    alen = sizeof(cad);
    if((sd2=accept(sd,(struct sockaddr *)&cad, &alen))<0) {
        fprintf(stderr,"accept failed \n");
        close(sd);
        exit(1);
    }

    close(sd);
    /* receive a package from client */        
    recv(sd2,buf,sizeof(buf),0);
    printf("\nData received: %s\n", buf);

    /* send a package to client */
    sprintf(buf,"From the Server\n");
    send(sd2,buf,strlen(buf),0);

    close(sd2);
    exit(0);
} 
