Interview Questions

Socket Programming in C using TCP with Code

An Introduction to Socket Programming


(Continued from previous question...)

Socket Programming in C using TCP with Code


To compile :

* linux : gcc -Wall -o foo foo.c
* solaris :gcc -Wall -o foo foo.c -lsocket -lnsl

1. TCP

* TCP server : simple TCP server 
that prints received messages.
         source : tcpServer.c
         usage : ./tcpServer
* TCP client : simple TCP client 
that sends data to server.
         source : tcpClient.c
usage :./tcpClient server data1...dataN


/*********** tcpserver.c **********/
by : prasad
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>/*close*/


#define SUCCESS 0
#define ERROR    1

#define END_LINE 0x0
#define SERVER_PORT 1500
#define MAX_MSG 100

/* function readline */
int read_line();

int main (int argc, char *argv[])
{
   
   int sd, newSd, cliLen;

struct sockaddr_in cliAddr, servAddr;
   char line[MAX_MSG];


   /* create socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
    if(sd<0) {
      perror("cannot open socket ");
      return ERROR;
   }
   
/* bind server port */
   servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
   servAddr.sin_port = htons(SERVER_PORT);
   
if(bind(sd, (struct sockaddr *) &servAddr, 
sizeof(servAddr))<0) {
      perror("cannot bind port ");
      return ERROR;
   }

   listen(sd,5);
   
   while(1) {

printf("%s: waiting for data on port TCP %u\n"
,argv[0],SERVER_PORT);

      cliLen = sizeof(cliAddr);
newSd = accept(sd, (struct sockaddr *)
   &cliAddr, &cliLen);
      if(newSd<0) {
 perror("cannot accept connection ");
         return ERROR;
      }
      
      /* init line */
      memset(line,0x0,MAX_MSG);
      
      /* receive segments */
while(read_line(newSd,line)!=ERROR) {
         
printf("%s: received from %s:TCP%d :
  %s\n", argv[0],
       inet_ntoa(cliAddr.sin_addr),
       ntohs(cliAddr.sin_port), line);
         /* init line */
         memset(line,0x0,MAX_MSG);
         
      } /* while(read_line) */
      
   } /* while (1) */

}


/* WARNING WARNING WARNING WARNING WARNING 
WARNING WARNING */
/* this function is experimental.. 
I don't know yet if it works */
/* correctly or not. Use Steven's 
readline() function to have */
/* something robust.       */
/* WARNING WARNING WARNING 
WARNING WARNING WARNING WARNING */

/* rcv_line is my function readline().
Data is read from the socket when */
/* needed, but not byte after bytes.
All the received data is read.   
 */
/* This means only one call to recv(),
instead of one call for         
    */
/* each received byte.    
    */
/* You can set END_CHAR to whatever 
means endofline for you. (0x0A is \n)*/
/* read_lin returns the number of 
bytes returned in line_to_return   
    */
int read_line(int newSd, char *line_to_return)
{
   
   static int rcv_ptr=0;
   static char rcv_msg[MAX_MSG];
   static int n;
   int offset;

   offset=0;

   while(1) {
      if(rcv_ptr==0) {
         /* read data from socket */
 memset(rcv_msg,0x0,MAX_MSG);
  /* init buffer */
 n = recv(newSd, rcv_msg, MAX_MSG, 0);
  /* wait for data */
         if (n<0) {
perror(" cannot receive data ");
return ERROR;
         } else if (n==0) {
printf(" connection closed by client\n");
close(newSd);
return ERROR;
         }
      }
   
      /* if new data read on socket */
      /* OR */
      /* if another line is still in buffer */

/* copy line into 'line_to_return' */
 while(*(rcv_msg+rcv_ptr)!=
END_LINE && rcv_ptr<n) {
memcpy(line_to_return+offset,rcv_msg+rcv_ptr,1);
         offset++;
         rcv_ptr++;
      }
      
/*end of line + end of buffer =<returnline*/
      if(rcv_ptr==n-1) {
         /* set last byte to END_LINE */
         *(line_to_return+offset)=END_LINE;
         rcv_ptr=0;
         return ++offset;
      }
      
/* end of line but still some data in 
buffer =>return line */

      if(rcv_ptr <n-1) {
 /* set last byte to END_LINE */
  *(line_to_return+offset)=END_LINE;
         rcv_ptr++;
         return ++offset;
      }

/* end of buffer but line is not ended =>*/
/* wait for more data to arrive on socket */
      if(rcv_ptr == n) {
         rcv_ptr = 0;
      }
      
   } /* while */
}


/******* tcpclient.c *******/


/* tcpClient.c */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /*close*/

#define SERVER_PORT 1500
#define MAX_MSG 100

int main (int argc, char *argv[]) {

   int sd, rc, i;
struct sockaddr_in localAddr, servAddr;
   struct hostent *h;
   
   if(argc < 3) {
 printf("usage: %s <server> <data1>
  <data2>  ... <dataN>\n",argv[0]);
      exit(1);
   }

   h = gethostbyname(argv[1]);
   if(h==NULL) {
      printf("%s: unknown host '%s'\n"
        ,argv[0],argv[1]);
      exit(1);
   }

servAddr.sin_family = h-<h_addrtype;
memcpy((char *) &servAddr.sin_addr.s_addr, 
h-<h_addr_list[0],h-<h_length);
   servAddr.sin_port = htons(SERVER_PORT);

   /* create socket */
   sd = socket(AF_INET, SOCK_STREAM, 0);
   if(sd<0) {
      perror("cannot open socket ");
      exit(1);
   }

   /* bind any port number */
   localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = 
     htonl(INADDR_ANY);
   localAddr.sin_port = htons(0);
   
   rc = bind(sd, (struct sockaddr *) &
      localAddr, sizeof(localAddr));
   if(rc<0) {
printf("%s: cannot bind port TCP %u\n",
  argv[0],SERVER_PORT);
      perror("error ");
      exit(1);
   }

   /* connect to server */
rc = connect(sd, (struct sockaddr *) 
   &servAddr, sizeof(servAddr));
   if(rc<0) {
      perror("cannot connect ");
      exit(1);
   }

   for(i=2;i<argc;i++) {
      
rc = send(sd, argv[i], strlen(argv[i])
   + 1, 0);
      
      if(rc<0) {
         perror("cannot send data ");
         close(sd);
         exit(1);
      
      }

printf("%s: data%u sent (%s)\n",
   argv[0],i-1,argv[i]);

   
   }

return 0;
   
}

Other Interview Questions