Pages

Subscribe:

Ads 468x60px

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

Friday, February 10, 2012

MySQL C++ Connection Example in Visual Studio

Creating a MySQL database connection using C++ is  really easy. But for a beginner it can be really hard to find the correct procedure cause it will gave really troubles. At the first time when I'm doing it it took me quite some time to make it work. So I'm going to explain how to make a connection to the MySQL database using C++ code. We use the library called boost to make the connection. 

Step 1 (Download the boost library)
First step is to download the boost library. You can download it from here from the official download page Or you can download the one I've compressed and uploaded which is smaller in size from here.

Step 2 (Create the project using Visual Studio 2008)
First go  to File --> New --> Project and you'll get a screen like this. 

mysql c++ connection example

Select Visual C++ --> Win 32 --> Win 32 Console Application  and give a name to the project and press OK. 
Then set Application Type to Console Application and remember to tick the empty project. and click finish.

Then Right Click the project and add new Item a cpp source file called Connect.cpp.

// Standard includes
#include 
#include 
#include 
using namespace std;

// Connector Includes

#include "cppconnection/driver.h"
#include "cppconnection/exception.h"
#include "cppconnection/resultset.h"
#include "cppconnection/statement.h"


// Link to the Connector/C++ library
#pragma comment(lib, "mysqlcppconn.lib")

// Connection details
string server   = "localhost";
string username = "root";
string password = "123"; // 

int main(){
    sql::Driver     *driver; // MySQL Driver Object
    sql::Connection *connection; // MySQL connection Object
    sql::Statement  *statement;   // Statement which holds SQL commands
    sql::ResultSet  *resultSet;    // ResultSet to hold the results
    //Here is the connection
    try{
        driver = get_driver_instance();
        connection = driver->connect(server, username, password);
        statement = connection->createStatement();
        statement->execute("USE performance_schema");
        resultSet = statement->executeQuery("show tables");
        while (resultSet->next()){
            // Iterating the result set
            cout << resultSet->getString(1) << endl;                
        }
    }
    catch (sql::Exception e){
        cout << "Error message: " << e.what() << endl;
        system("pause");
        exit(1);
    }

    //Clear resources
    delete res;
    delete statement;
    delete connection;

    system("pause");
    return 0;
}

Copy the boost folder into the project folder. In this example the folder is Visual Studio 2008\Projects\MySQLConnection\MySQLConnection folder.

Then download this header and dll files and extract them into the same folder Visual Studio 2008\Projects\MySQLConnection\MySQLConnection folder.

Then the final step is right cilck on the Project and go to 
Properties --> Configuration Properties --> C/C++ --> General . 
On the right hand side set the "Additional Include Directories" value to ".\" value. (with out the quotes)

That's it build your project and run the project. And one more final thing when you run the project set the  "Solution Configuration" to Release mode. In the Debug Mode I had some error which I still don't no why.

So that's it now I think you got a clear idea about creating a connection for MySQL using C++ in Visual Studio 2008. See you around with another exciting post... :)