Thursday, June 5, 2014

Playing with the sockets !


We shall look into another way of achieving IPC (inter process communication)
, which is socket communication . I have used the client server model to demonstrate the socket communication.

Important things to consider in the socket communication .

1. Port Number associated with the socket .
2. Address family i.e IPv4 or IPv6
2. How many Clients can the server accepts ?
3. Different ways of connecting the socket from the same machine(node) or different machine.



Server.c

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include<string.h>

#define PORT_NUM 5000

void main()
{
  int sock_fd;
  int connection_fd;
  struct sockaddr_in serv_addr;
  char buffer_to_send[32];
  /*AF_INET  - Internet IP Protocol *
   *SOCK_STREAM - stream socket
   * protocol - 0- un specified .. by default we give this option for now !! */

  sock_fd = socket(AF_INET,SOCK_STREAM,0) ;

  if(sock_fd <0)
   {
    printf("Cannot create socket \n");
    return ;
   }

  /*Address family INET i.e. ipv4
   *source address any address
   *Port specified by the PORT_NUM */

  serv_addr.sin_family = AF_INET;

  /* This INADDR_ANY allowed our program to work without knowing the IP address
   * of the machine it is being run */
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

  /*htons is required here to convert into the network byte order*/
  serv_addr.sin_port = htons(PORT_NUM);

  /*Tricky part here ... we are updating the serv_addr and converting the same into
   *sockadd type .. both are same but different way of representing the data
   * bind call expects it to be in the later form*/
  bind(sock_fd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));


  if ( listen(sock_fd,1) == -1)
   {
    printf("Cannot listen on the socket \n");
    return ;
   }


  while(1)
    {

      /*Accept is used for establishing the connection with the client node when it tries to request for
       * the connection , we can correlate the same to 3 way TCP handshake
       * Second argument structure is filled in with the address of the peer socke we can ignore that by passing NULL
       * in that case third which is the length of the data for second argument can also be NULL*/

      connection_fd = accept(sock_fd, (struct sockaddr*)NULL ,NULL);

      strcpy(buffer_to_send, "Message from server");
      write(connection_fd, buffer_to_send, strlen(buffer_to_send));

      /*Upon successfull xmission of a msg close the socket , when the client requests for one more session
       *It will unblock from the accept call and proceeds further for seding the data  */
      close(connection_fd);
      sleep(1);
   }


}


Client.c


#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include<string.h>
#include<errno.h>

#define PORT_NUM 5000

void main(int argc, char *argv[])
{
  int sock_fd;
  int connection_fd;
  int num_bytes;
  struct sockaddr_in client_addr;
  char recv_buffer[32];
  int ret;
  /*AF_INET  - Internet IP Protocol *
   *SOCK_STREAM - stream socket
   * protocol - PF_UNIX - used for internal communication */

  sock_fd = socket(AF_INET,SOCK_STREAM,0) ;

  if(argc != 2)
  {
      printf("\n Usage: %s <server_ip> \n",argv[0]);
      return ;
  }

  if(sock_fd <0)
   {
    printf("Cannot create socket \n");
    return ;
   }

  /*Address family INET i.e. ipv4
   *source address any address
   *Port specified by the PORT_NUM */

  client_addr.sin_family = AF_INET;


   if(inet_pton(AF_INET, argv[1], &client_addr.sin_addr)<=0)
    {
        printf("\n inet_pton error occured\n");
        return ;
    }

  /*htons is required here to convert into the network byte order*/
  client_addr.sin_port = htons(PORT_NUM);

  /*Tricky part here ... we are updating the client_addr and converting the same into
   *sockadd type .. both are same but different way of representing the data
   * bind call expects it to be in the later form*/
  ret = connect(sock_fd, (struct sockaddr*)&client_addr,sizeof(client_addr));
  //if(connect(sock_fd, (struct sockaddr*)&client_addr,sizeof(client_addr)) < 0)
  if(ret<0)
   {
     printf("Connection failed error = %s\n" , strerror(errno));
     return ;
   }


  while((num_bytes = read(sock_fd, recv_buffer, sizeof(recv_buffer)-1)) > 0)
    {
      recv_buffer[num_bytes] = 0;
      if(fputs(recv_buffer, stdout) == EOF)
       {
         printf("\n Error : Fputs error");
       }
      printf("\n");
    }

}





Output :

Here i am running server in one machine and trying to connect from two different machines ( 2 clients ) , If you look at the code i am listening for only one connection for that socket ... listen system call in the server

One can play with the number of clients options and see how it behaves differently !


# ./socket_client 127.0.0.1
Message from server

# ./socket_client 10.10.27.203
Connection failed error = Connection refused

To verify if the socket really is in listen state , we can check for the netstat o/p as follows

#netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 0.0.0.0:5000                0.0.0.0:*                   LISTEN      437/./socket_server




No comments:

Post a Comment