Pages

Subscribe:

Ads 468x60px

Showing posts with label Programming Languages. Show all posts
Showing posts with label Programming Languages. 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.. :)

Tuesday, February 7, 2012

Syntax and Semantics of a Programming Language


Syntax of a Programming Language

The  Syntax  of  a  Programming  Language  is  the  set  of  rules  that  defined  in  that programming language in order to express how the combinations of symbols are formed.
Syntax is differed into two main categories.
  • Abstract Syntax  -->     Provide definition for the constructs
  • Concrete Syntax  -->       Provide definitions of the form of the constructs
E.g. In Java while loop is defined as
While(booleanValue){
//Statements goes  here
}

Semantics of a Programming Language

Semantics reveals  the  meaning  of a  syntacticallcorrect  programming  language  in expressions, statements, program units. Semantics of a programming language also can be divided into two different categories.


Static Semantics

For compiled languages static semantics are usually tested at the compile time.

E.g. checking that every identifier is declared before it is used (in languages that require such declarations)

Dynamic Semantics


As the above classification there are three types of Dynamic Semantics. Dynamic Semantics are usually tested  while at the runtime. Dynamic Semantics of a Programming language defines  how and  when the various  constructs of a  language should  produce a program behavior.

e.g In java
if(a==b){
return;
}

Meaning of this statement is derived by executing this program on a computer. (This is what we called operational semantics also in the same category of Dynamic semantics)

Ambiguity of a Programming Language

If a statement constructed by using a particular grammar has more than one parse tree; it is said to be that grammar is ambiguous.

E.g. Simple example

<E> --> <D> 
  <E> --> <E>
  <E> --> <E> + <E> |<E> - <E> |<E> * <E> |<E> / <E>
  <D> --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
Lets consider statement  1+2*5  for the above grammar




Above grammar is ambiguous since it has two parse trees and the left derivation tree give the answer 11 which is correct and the right derivation tree gives 15 which is incorrect.