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

  1. /*
  2.  * CHttpClient.h
  3.  *
  4.  *  Created on: 11-mar-2009
  5.  *      Author: Fabrizio Caldarelli
  6.  *        Mail: fabriziocaldarelli@negusweb.it
  7.   */
  8.  
  9. #ifndef CHTTPCLIENT_H_
  10.  
  11. #include <stdio.h>
  12. #include <sys socket.h="">
  13. #include <arpa inet.h="">
  14. #include <stdlib.h>
  15. #include <netdb.h>
  16. #include <string.h>
  17. #include <iostream>
  18. #include <string>
  19.  
  20. using namespace std;
  21.  
  22.  
  23. class CHttpClient
  24. {
  25. public:		// Publics Methods
  26. 	int DoHttpGetRequest(string& oHttpHeader, string& oHttpBody);
  27.  
  28. public:		// Constructors
  29. 	CHttpClient(const string& iHostName, const string& iPage);
  30.  
  31. private:	// Privates Methods
  32. 	int _CreateTcpSocket();
  33. 	int _GetIp(const string& iHostName,string& oIp);
  34. 	int _BuildGetQuery(const string& iHostName, const string& iPage, string& oQueryGet);
  35.  
  36. private:	// Privates Members
  37. 	string hostName;
  38. 	string page;
  39.  
  40. };
  41.  
  42.  
  43. #define CHTTPCLIENT_H_
  44.  
  45.  
  46. #endif /* CHTTPCLIENT_H_ */



inc/HttpClient/CHttpClient.cpp

  1. /*
  2.  * CHttpClient.cpp
  3.  *
  4.  *  Created on: 11-mar-2009
  5.  *      Author: Fabrizio Caldarelli
  6.  *        Mail: fabriziocaldarelli@negusweb.it
  7.   */
  8.  
  9. #include "HttpClient/CHttpClient.h"
  10.  
  11. int CHttpClient::_CreateTcpSocket()
  12. {
  13. 	int sock;
  14. 	if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
  15. 		perror("Can't create TCP socket");
  16. 		exit(1);
  17. 	}
  18. 	return sock;
  19. }
  20.  
  21. int CHttpClient::_GetIp(const string& iHostName,string &oIp)
  22. {
  23. 	struct hostent *hent;						// distruggere *hent
  24. 	int iplen = 15; //XXX.XXX.XXX.XXX
  25. 	char *ip = (char *)malloc(iplen+1);			// distruggere *ip
  26. 	memset(ip, 0, iplen+1);
  27. 	if((hent = gethostbyname(iHostName.c_str())) == NULL)
  28. 	{
  29. 		herror("Can't get IP");
  30. 		exit(1);
  31. 	}
  32. 	if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
  33. 	{
  34. 		perror("Can't resolve host");
  35. 		exit(1);
  36. 	}
  37.  
  38. 	// Assign value output parameter oIp
  39. 	oIp.append(ip);
  40.  
  41. 	free(ip);
  42.  
  43. 	// Function return code
  44. 	return 0;
  45. }
  46.  
  47. int CHttpClient::_BuildGetQuery(const string& iHostName,const string& iPage,string& oQueryGet)
  48. {
  49. 	char *query;								// distruggere *query
  50. 	char *getPage = new char[iPage.length()+1];	// distruggere *getPage
  51. 	strcpy(getPage,iPage.c_str());
  52.  
  53. 	string UserAgent("HTMLGET 1.0");
  54.  
  55. 	char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";	// distruggere *tpl
  56. 	if(getPage[0] == '/'){
  57. 		getPage = getPage + 1;
  58. 		fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", iPage.c_str(), getPage);
  59. 	}
  60. 	// -5 is to consider the %s %s %s in tpl and the ending \0
  61. 	query = (char *)malloc(iHostName.length()+strlen(getPage)+UserAgent.length()+strlen(tpl)-5);
  62. 	sprintf(query, tpl, getPage, iHostName.c_str(), UserAgent.c_str());
  63.  
  64. 	// Assign Query Get Output value
  65. 	oQueryGet = query;
  66.  
  67. 	// Free memory
  68. 	free(query);
  69. 	delete [] getPage;
  70.  
  71. 	// Function return code
  72. 	return 0;
  73. }
  74.  
  75. CHttpClient::CHttpClient(const string& iHostName, const string& iPage)
  76. {
  77. 	this->hostName.append(iHostName);
  78. 	this->page.append(iPage);
  79. }
  80.  
  81. int CHttpClient::DoHttpGetRequest(string& oHttpHeader,string& oHttpBody)
  82. {
  83. 	char buf[BUFSIZ+1];
  84.  
  85.  
  86. 	int tmpres;
  87. 	int sock;
  88. 	string ip;
  89. 	string queryGet;
  90. 	struct sockaddr_in remote;
  91.  
  92.  
  93.  
  94. 	sock = this->_CreateTcpSocket();
  95.  
  96. 	this->_GetIp(this->hostName, ip);
  97.  
  98. 	fprintf(stderr, "IP is %s\n", ip.c_str());
  99.  
  100. 	//remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
  101. 	remote.sin_family = AF_INET;
  102. 	tmpres = inet_pton(AF_INET, ip.c_str(), (void *)(&(remote.sin_addr.s_addr)));
  103. 	if( tmpres < 0)
  104. 	{
  105. 		perror("Can't set remote->sin_addr.s_addr");
  106. 		exit(1);
  107. 	}else if(tmpres == 0)
  108. 	{
  109. 		fprintf(stderr, "%s is not a valid IP address\n", ip);
  110. 		exit(1);
  111. 	}
  112. 	remote.sin_port = htons(80);
  113. 	if(connect(sock, (struct sockaddr *)&remote, sizeof(struct sockaddr)) < 0){
  114. 		perror("Could not connect");
  115. 		exit(1);
  116. 	}
  117.  
  118. 	this->_BuildGetQuery(this->hostName,this->page,queryGet);
  119.  
  120. 	fprintf(stderr, "Query is:\n<<start>>\n%s<<end>>\n", queryGet.c_str());
  121.  
  122. 	//Send the query to the server
  123. 	int sent = 0;
  124. 	while(sent < queryGet.length())
  125. 	{
  126. 		tmpres = send(sock, queryGet.c_str()+sent, queryGet.length()-sent, 0);
  127. 		if(tmpres == -1){
  128. 			perror("Can't send query");
  129. 			exit(1);
  130. 		}
  131. 		sent += tmpres;
  132. 	}
  133.  
  134. 	//now it is time to receive the page
  135. 	memset(buf, 0, sizeof(buf));
  136. 	int htmlstart = 0;
  137. 	char * htmlcontent;
  138.  
  139. 	char* chHttpResponse;
  140. 	string httpResponse = "";
  141. 	while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0)
  142. 	{
  143. 		chHttpResponse = new char[tmpres+1];
  144. 		strncpy(chHttpResponse,buf,tmpres);
  145. 		httpResponse.append(chHttpResponse);
  146. 		delete [] chHttpResponse;
  147. 		memset(buf, 0, tmpres);
  148. 	}
  149. 	if(tmpres < 0)
  150. 	{
  151. 		perror("Error receiving data");
  152. 	}
  153.  
  154. 	// Split httpResponse in httpHeader and httpBody
  155. 	int separator = httpResponse.find("\r\n\r\n");
  156.  
  157. 	// If separator not found, return npos. So, only header and not body
  158. 	oHttpHeader = "";
  159. 	oHttpBody = "";
  160.  
  161. 	if (separator == string::npos)
  162. 	{
  163. 		oHttpHeader.append(httpResponse);
  164. 	}
  165. 	else
  166. 	{
  167. 		oHttpHeader.append(httpResponse.substr(0,separator));
  168. 		separator += 4;
  169. 		oHttpBody.append(httpResponse.substr(separator,httpResponse.length()-separator));
  170. 	}
  171.  
  172. 	close(sock);
  173. 	return 0;
  174. }

Allegati

Pacchetto Completo Sorgenti Client Http Get su Linux

Strumenti personali
hobby
approfondimenti