Pages

Subscribe:

Ads 468x60px

Showing posts with label TCP. Show all posts
Showing posts with label TCP. Show all posts

Friday, January 18, 2013

How to send Complex Data Structures in a Socket Program

Hi all, Hope you guys are doing well. I was busy with my work last few days. Today I'm going to write a post about sending Complex data structures using a socket program. In this post I assume that you are somewhat familiar with the socket programming basics.

In the following example we are creating a Object type in the server program and send that to the client program. This is a simple serialize and deserialize mechanism to send complex data structures through a socket program using only the STL library. If you want more complex and complete functionality you might try the boost library. 

Here we are going to send the following data structure.
 Data.h File
class InnerData{
    public:
    int c;
};

class Data{
    public:
    int a;
    char b[20];
    InnerData id;
  
};

Now we write the Server program which will create a socket, bind that socket to a port and listen for incoming connections. If there is a incoming connection accept the connection, serialize the data send to the connected client.

Server.cpp File
#include <stdio.h>
#include <cstdlib> 
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <arpa/inet.h> 
#include "Data.h"

int main(int argc , char * argv [])
{
    int SockFD , NewSockFD , PortNo, Clilen;
    char Buffer[1024];
 struct sockaddr_in Server_Addr , Cli_Addr;
 int n , pID;

 //create a socket
 SockFD =  socket(AF_INET , SOCK_STREAM , 0);
 if(SockFD < 0)
 {
  perror("Error Creating Socket \n");
  exit(1);
 }
 std::cout << "Socket Created..." << std::endl;

 bzero((char *) &Server_Addr , sizeof(Server_Addr));
 PortNo = atoi(argv[1]);
 Server_Addr.sin_family = AF_INET;
 Server_Addr.sin_addr.s_addr = INADDR_ANY;
 Server_Addr.sin_port = htons(PortNo);

 
 //bind the socket
 if(bind(SockFD , (struct sockaddr *) &Server_Addr , sizeof(Server_Addr)) < 0)
 {
  perror("Error Binding \n");
  exit(1);
 }
 std::cout << "Socket Binded..." << std::endl;
 //listen for incoming clients
 listen(SockFD , 5);
 Clilen =  sizeof(Cli_Addr);
 std::cout << "Waiting For Connections..." << std::endl;
 
 while(1)
 {
  //accept a client 
  NewSockFD = accept(SockFD , (struct sockaddr *) &Cli_Addr ,(socklen_t *) &Clilen);
  printf("New Client %d \n", NewSockFD);
  if(NewSockFD < 0)
  {
   perror("Error accepting \n");
   exit(1);
  }  
   bzero(Buffer , 1024);
   printf("New Client Connected, Process ID :: %d \n",pID);
   //create the Data
   Data *data = new Data();
   data->a = 23232;
   strcpy(data->b , "TEST MESSAGE" );
   data->id.c =1000;
  
   n =  write(NewSockFD , data ,sizeof(*data) );
   if(n < 0)
   {
    perror(" Error Sending Message \n");
    exit(1);
   }
  
 }
 return 0;
}

Now the client accept the data send by the client and deserialize it.

Client.cpp
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h> 
#include "Data.h"


int main(int argc , char * argv [])
{
 int SockFD , PortNo , n;
 struct sockaddr_in Server_Address;
 struct hostent *Server;
 
 char Buffer[1024]; // Buffer to read data

 if(argc < 3)
 {
  printf("Error hostname port required \n");
  exit(0);
 }
 PortNo = atoi(argv[2]);
 // create a socket 
 SockFD =  socket(AF_INET , SOCK_STREAM , 0);

 if(SockFD < 0 )
 {
  perror("Error Creating Socket");
  exit(1);
 }
 
 Server = (struct hostent *) gethostbyname(argv[1]);
 if(Server == NULL)
 {
  printf("Error :: No Such Host \n");
  exit(0);
 }

 bzero((char *) &Server_Address , sizeof(Server_Address));
 Server_Address.sin_family =  AF_INET;
 bcopy((char *) Server->h_addr , (char *) &Server_Address.sin_addr.s_addr , Server->h_length);
 
 Server_Address.sin_port = htons(PortNo);
 
 //connect to the server
 if(connect(SockFD , (struct sockaddr *) &Server_Address , sizeof(Server_Address)) < 0)
 {
  perror("Error Connecting \n");
  exit(1);
 }
 Data * data = new Data();
 n = read(SockFD , Buffer , sizeof(Data));
 data = (Data *) Buffer;
 printf("Read Size %d \n" , n);
 if(n < 0)
 {
  perror("Error receiving data \n");
  exit(1);
 }
 printf("Received :: ID :: %d  MESSAGE :: %s Complex ID:: %d \n", data->a , data->b ,data->id.c );
 bzero(Buffer , 1024);

 return 0;

}

First we compile the Server.cpp file
g++ -o Server Server.cpp

Then we run the server giving the port as an argument.
./Server  7788

Then compile and run the client program using a new terminal.
g++ -o Client Client.cpp

./Client localhost 7788

That's it folks. It's a simple approach. But solve the problem. Remember that this only works since we are using the same computer architecture. If you are using different architectures you have to consider about the endian problem also.. :)

Wednesday, October 24, 2012

Network Simulation using NS2

Before deploying a network it is necessary to check how the network would behave after the deployment. After deploying the network sometime it may not function/behave as expected. So it is better to get some idea before the real deployment. 

There are commercial simulators of course,  but the problem is that they are very expensive. So NS2 come in handy, since it's free and opensource. The script files you write in NS2 is .tcl 

First of all you have to install NS2 in your computer. Just enter the following command and it will be installed.

[aruna@ubuntu]~$ sudo apt-get install ns2 nam

Now you have installed NS2. (I am not going to teach you how to write .tcl scripts there are enough tutorials on how to write .tcl scripts. I just want to give you a simple introduction to what is NS2 and what it is capable of.)
The following code creates six nodes 0,1,2,3,4 and 5 and there are two tcp connections from node 0 to 5 and the other from node 1 to 4. You can see how the data packet travel through the links and even you can analyze each data packet.

Download Code Link :   Download 

#**********************************************************************
 # Sample tcp.tcl file 
#*********************************************************************/


#Create a simulator object
set ns [new Simulator]

$ns color 1 Blue
$ns color 2 Red
$ns color 3 Green

#Open the nam trace file
set nf [open out.nam w]
$ns namtrace-all $nf

#Define a 'finish' procedure
proc finish {} {
        global ns nf f0 f1
        $ns flush-trace
 #Close the trace files
        close $nf
 #Execute nam on the trace file
        exec nam out.nam &
        exit 0
}
#Create two nodes
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]
set n3 [$ns node]
set n4 [$ns node]
set n5 [$ns node]

#Create a duplex link between the nodes
$ns duplex-link $n0 $n2 1Mb 10ms DropTail 
$ns duplex-link $n1 $n2 1Mb 10ms DropTail 
$ns duplex-link $n2 $n3 1Mb 10ms DropTail 
$ns duplex-link $n3 $n4 1Mb 10ms DropTail 
$ns duplex-link $n3 $n5 1Mb 10ms DropTail 

#give node position
$ns duplex-link-op $n0 $n2 orient right-down 
$ns duplex-link-op $n1 $n2 orient right-up 
$ns duplex-link-op $n2 $n3 orient right 
$ns duplex-link-op $n3 $n4 orient right-up 
$ns duplex-link-op $n3 $n5 orient right-down

#Create a TCP agent and attach it to node n0
set tcp0 [new Agent/TCP]
$ns attach-agent $n0 $tcp0
set sink0 [new Agent/TCPSink]
$ns attach-agent $n5 $sink0
$ns connect $tcp0 $sink0
$tcp0 set fid_ 3

#Create a TCP agent and attach it to node n1
set tcp1 [new Agent/TCP]
$ns attach-agent $n1 $tcp1
set sink1 [new Agent/TCPSink]
$ns attach-agent $n4 $sink1
$ns connect $tcp1 $sink1
$tcp1 set fid_ 2

# Create a CBR traffic source and attach it to tcp1
set ftp0 [new Application/FTP]
$ftp0 set packetSize_ 500
$ftp0 set interval_ 0.005
$ftp0 attach-agent $tcp1
$ftp0 set rate_ 3mb
$ftp0 set random_ false

# Create a CBR traffic source and attach it to tcp0
set ftp1 [new Application/FTP]
$ftp1 set packetSize_ 500
$ftp1 set interval_ 0.005
$ftp1 attach-agent $tcp0
$ftp1 set rate_ 3mb
$ftp1 set random_ false

#Schedule events for the CBR agent
$ns at 0.0 "$ftp0 start"
$ns at 1.0 "$ftp1 start"
$ns at 5.0 "$ftp0 stop"
$ns at 5.0 "$ftp1 stop"

#Call the finish procedure after 5 seconds of simulation time
$ns at 5.0 "finish"

#Run the simulation
$ns run
To run the following code just type 

[aruna@ubuntu]~$ ns tcp.tcl



Hope you'll enjoy NS2... :)