Mangiare Senza Glutine disponibile su App Store

Per altre informazioni scrivi a fabriziocaldarelli@negusweb.it

Socket Http Client in C++ su Linux (GET)

Da Programmazione Software.

Descrizione

Capita spesso di dover accedere a pagine web attraverso C++, molto spesso per accedere al contenuto di risorse XML tramite protocollo http, quindi usando il metodo GET.

Qui di seguito il codice sorgente di un client Http (solo metodo GET) incapsulato in un'apposita classe, in modo da avere codice pulito ed organizzato.

Il client si inizializza passando HostName e Pagina da visualizzare (in realtà si può fare un metodo che splitta una url completa, magari questo nella versione 2.0), dando per scontato che la porta di connessione sia l'80.

Al momento è possibile solo usare il metodo GET, probabilmente seguirà una nuova versione con il metodo POST, il passaggio di una url completa al costruttore e la possibilità di definire la porta.

Insieme al client, un piccolo programma per utilizzarlo che scrive in un path specifico (in questo caso /home/negus) i files relativi all'header ed al body della risposta.

Alla fine del codice lo zip del programma.

Buona lettura.


inc/HttpClient/CHttpClient.h

/*
 * CHttpClient.h
 *
 *  Created on: 11-mar-2009
 *      Author: Fabrizio Caldarelli
 *        Mail: fabriziocaldarelli@negusweb.it
  */
 
#ifndef CHTTPCLIENT_H_
 
#include <stdio.h>
#include <sys socket.h="">
#include <arpa inet.h="">
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <iostream>
#include <string>
 
using namespace std;
 
 
class CHttpClient
{
public:		// Publics Methods
	int DoHttpGetRequest(string& oHttpHeader, string& oHttpBody);
 
public:		// Constructors
	CHttpClient(const string& iHostName, const string& iPage);
 
private:	// Privates Methods
	int _CreateTcpSocket();
	int _GetIp(const string& iHostName,string& oIp);
	int _BuildGetQuery(const string& iHostName, const string& iPage, string& oQueryGet);
 
private:	// Privates Members
	string hostName;
	string page;
 
};
 
 
#define CHTTPCLIENT_H_
 
 
#endif /* CHTTPCLIENT_H_ */



inc/HttpClient/CHttpClient.cpp

/*
 * CHttpClient.cpp
 *
 *  Created on: 11-mar-2009
 *      Author: Fabrizio Caldarelli
 *        Mail: fabriziocaldarelli@negusweb.it
  */
 
#include "HttpClient/CHttpClient.h"
 
int CHttpClient::_CreateTcpSocket()
{
	int sock;
	if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
		perror("Can't create TCP socket");
		exit(1);
	}
	return sock;
}
 
int CHttpClient::_GetIp(const string& iHostName,string &oIp)
{
	struct hostent *hent;						// distruggere *hent
	int iplen = 15; //XXX.XXX.XXX.XXX
	char *ip = (char *)malloc(iplen+1);			// distruggere *ip
	memset(ip, 0, iplen+1);
	if((hent = gethostbyname(iHostName.c_str())) == NULL)
	{
		herror("Can't get IP");
		exit(1);
	}
	if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
	{
		perror("Can't resolve host");
		exit(1);
	}
 
	// Assign value output parameter oIp
	oIp.append(ip);
 
	free(ip);
 
	// Function return code
	return 0;
}
 
int CHttpClient::_BuildGetQuery(const string& iHostName,const string& iPage,string& oQueryGet)
{
	char *query;								// distruggere *query
	char *getPage = new char[iPage.length()+1];	// distruggere *getPage
	strcpy(getPage,iPage.c_str());
 
	string UserAgent("HTMLGET 1.0");
 
	char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";	// distruggere *tpl
	if(getPage[0] == '/'){
		getPage = getPage + 1;
		fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", iPage.c_str(), getPage);
	}
	// -5 is to consider the %s %s %s in tpl and the ending \0
	query = (char *)malloc(iHostName.length()+strlen(getPage)+UserAgent.length()+strlen(tpl)-5);
	sprintf(query, tpl, getPage, iHostName.c_str(), UserAgent.c_str());
 
	// Assign Query Get Output value
	oQueryGet = query;
 
	// Free memory
	free(query);
	delete [] getPage;
 
	// Function return code
	return 0;
}
 
CHttpClient::CHttpClient(const string& iHostName, const string& iPage)
{
	this->hostName.append(iHostName);
	this->page.append(iPage);
}
 
int CHttpClient::DoHttpGetRequest(string& oHttpHeader,string& oHttpBody)
{
	char buf[BUFSIZ+1];
 
 
	int tmpres;
	int sock;
	string ip;
	string queryGet;
	struct sockaddr_in remote;
 
 
 
	sock = this->_CreateTcpSocket();
 
	this->_GetIp(this->hostName, ip);
 
	fprintf(stderr, "IP is %s\n", ip.c_str());
 
	//remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
	remote.sin_family = AF_INET;
	tmpres = inet_pton(AF_INET, ip.c_str(), (void *)(&(remote.sin_addr.s_addr)));
	if( tmpres < 0)
	{
		perror("Can't set remote->sin_addr.s_addr");
		exit(1);
	}else if(tmpres == 0)
	{
		fprintf(stderr, "%s is not a valid IP address\n", ip);
		exit(1);
	}
	remote.sin_port = htons(80);
	if(connect(sock, (struct sockaddr *)&remote, sizeof(struct sockaddr)) < 0){
		perror("Could not connect");
		exit(1);
	}
 
	this->_BuildGetQuery(this->hostName,this->page,queryGet);
 
	fprintf(stderr, "Query is:\n<<start>>\n%s<<end>>\n", queryGet.c_str());
 
	//Send the query to the server
	int sent = 0;
	while(sent < queryGet.length())
	{
		tmpres = send(sock, queryGet.c_str()+sent, queryGet.length()-sent, 0);
		if(tmpres == -1){
			perror("Can't send query");
			exit(1);
		}
		sent += tmpres;
	}
 
	//now it is time to receive the page
	memset(buf, 0, sizeof(buf));
	int htmlstart = 0;
	char * htmlcontent;
 
	char* chHttpResponse;
	string httpResponse = "";
	while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0)
	{
		chHttpResponse = new char[tmpres+1];
		strncpy(chHttpResponse,buf,tmpres);
		httpResponse.append(chHttpResponse);
		delete [] chHttpResponse;
		memset(buf, 0, tmpres);
	}
	if(tmpres < 0)
	{
		perror("Error receiving data");
	}
 
	// Split httpResponse in httpHeader and httpBody
	int separator = httpResponse.find("\r\n\r\n");
 
	// If separator not found, return npos. So, only header and not body
	oHttpHeader = "";
	oHttpBody = "";
 
	if (separator == string::npos)
	{
		oHttpHeader.append(httpResponse);
	}
	else
	{
		oHttpHeader.append(httpResponse.substr(0,separator));
		separator += 4;
		oHttpBody.append(httpResponse.substr(separator,httpResponse.length()-separator));
	}
 
	close(sock);
	return 0;
}

Allegati

Pacchetto Completo Sorgenti Client Http Get su Linux