相关文章推荐

前面的文章《 Libcurl编译指南——Android和Windows系统 》已经就libcurl在Windows和Android系统编做了详细的说明。
本文档用C/C++实现简单的HTTP/HTTPS客户端,支持get和post,支持保持session和长连接。

httpConn.h

#ifndef __HTTP_CONN_H__
#define __HTTP_CONN_H__
#include "curl.h"
#define RETRY_TIMES	3
struct MemoryStruct {
	char			*memory;
	unsigned int	size;
class RequestHandler
private:
public:
	MemoryBlock		request;
	MemoryBlock     response;
	int				http_code;
class HttpRequest
private:
	CURL				*curl_handle;
	CURLcode			curl_res;
	long				http_code;
	struct MemoryStruct receive_header;
	struct MemoryStruct receive_content;
	struct MemoryStruct error_message;
	struct curl_slist	*http_headers;
	int					retry_times;
public:
	HttpRequest();
	~HttpRequest();
	int			setRequestUrl(const char *url);	// 设置URL
	int			setRequestHeader(const char *header); // 设置Header
	int			setRequestTimeout(long time); // 设置超时时间
	int			setPostData(const char *data, unsigned int size); // 设置post数据
	int			setResultCallback(); // 回调
	int			performRequest(); // 发送数据
	int			sendReceiveEx(const char *url, RequestHandler *handler); // 发送和接收url请求
	int			getHttpCode(); //返回http code
	int			getHeader(char *header, unsigned int *len); // 返回Header
	int			getContent(char *content, unsigned int *len);
#endif

httpConn.cpp

#include "httpConn.h"
#include "curl.h"
static unsigned int RetriveContentCallback(void *contents, unsigned int size, unsigned int nmemb, void *userp)
	unsigned int realsize = size * nmemb;
	struct MemoryStruct *mem = (struct MemoryStruct *)userp;
	char *ptr = (char*)realloc((void *)mem->memory, mem->size + realsize + 1);
	if (ptr == NULL) {
		/* out of memory! */
		printf("not enough memory (realloc returned NULL)\n");
		return -6;
	mem->memory = ptr;
	memcpy(&(mem->memory[mem->size]), contents, realsize);
	mem->size += realsize;
	mem->memory[mem->size] = 0;
	return realsize;
static unsigned int RetriveHeaderCallback(void *contents, unsigned int size, unsigned int nmemb, void *userp)
	unsigned int realsize = size * nmemb;
	struct MemoryStruct *mem = (struct MemoryStruct *)userp;
	char *ptr = (char*)realloc((void *)mem->memory, mem->size + realsize + 1);
	if (ptr == NULL) {
		/* out of memory! */
		printf("not enough memory (realloc returned NULL)\n");
		return -6;
	mem->memory = ptr;
	memcpy(&(mem->memory[mem->size]), contents, realsize);
	mem->size += realsize;
	mem->memory[mem->size] = 0;
	return realsize;
HttpRequest::HttpRequest()
	curl_res = CURLE_OK;
	http_code = 0;
	curl_handle = NULL;
	http_headers = NULL;
	retry_times = RETRY_TIMES;
	/* will be grown as needed by the realloc above */
	receive_content.memory = (char*)malloc(1); 
	receive_header.memory = (char*)malloc(1);
	error_message.memory = (char*)malloc(1);
	/* no data at this point */
	receive_content.size = 0;  
	receive_header.size = 0;
	/* global libcurl initialisation */
	curl_global_init(CURL_GLOBAL_ALL);
	/* init the curl session */
	curl_handle = curl_easy_init();
HttpRequest::~HttpRequest()
	/* cleanup curl stuff */
	if (curl_handle)
		curl_easy_cleanup(curl_handle);
	free(receive_content.memory);
	free(receive_header.memory);
	free(error_message.memory);
	if (http_headers)
		curl_slist_free_all(http_headers);
	/* we're done with libcurl, so clean it up */
	curl_global_cleanup();
int HttpRequest::setRequestUrl(const char *url)
	if (0 == memcmp(url, "https", 5))
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_SSL_VERIFYPEER failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_SSL_VERIFYHOST failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
#ifdef USE_PROXY
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_PROXY, PROXY_ADDRESS);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_PROXY failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
#endif // USE_PROXY
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_URL, url);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_URL failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	return 0;
int HttpRequest::setRequestHeader(const char * header)
	http_headers = curl_slist_append(http_headers, header);
	curl_res = http_headers ? CURLE_OK : CURLE_FAILED_INIT;
	if (CURLE_OK != curl_res)
		printf("Set request header: curl_slist_append failed.");
		return -2;
	return 0;
int HttpRequest::setRequestTimeout(long time)
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, time);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_TIMEOUT failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	return 0;
int HttpRequest::setPostData(const char *data, unsigned int size)
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_POST, 1);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_POST failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_POSTFIELDS failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, size);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_POSTFIELDSIZE failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	return 0;
int HttpRequest::setResultCallback()
	/* send all data to this function  */
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, RetriveContentCallback);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_WRITEFUNCTION failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	/* we pass our 'receive_content' struct to the callback function */
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&receive_content);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_WRITEDATA failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	/*curl_res = curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, RetriveHeaderCallback);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_HEADERFUNCTION failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	curl_res = curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)&receive_header);
	if (CURLE_OK != curl_res)
		printf("curl_easy_setopt CURLOPT_HEADERDATA failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
		return -1;
	return 0;
int HttpRequest::performRequest()
	if (curl_handle)
		setResultCallback();
		setRequestTimeout(10);
		if (http_headers)
			curl_res = curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, http_headers);
			if (CURLE_OK != curl_res)
				printf("curl_easy_setopt CURLOPT_HTTPHEADER failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
				return -1;
		/* some servers don't like requests that are made without a user-agent field, so we provide one */
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_USERAGENT failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_NOPROGRESS failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_NOSIGNAL failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT_MS, 0);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_CONNECTTIMEOUT_MS failed. curl_res = %d,  curl_strerror = %s", curl_res, curl_easy_strerror(curl_res));
			return -1;
		/* get it! */
		curl_res = curl_easy_perform(curl_handle);
		if (curl_res == CURLE_OPERATION_TIMEDOUT)
			int retry_count = retry_times;
			while (retry_count > 0)
				curl_res = curl_easy_perform(curl_handle);
				if (curl_res != CURLE_OPERATION_TIMEDOUT) break;
				retry_count--;
		if (curl_res == CURLE_OPERATION_TIMEDOUT)
			printf("curl_easy_perform failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -3;
		curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_code);
		if (curl_res != CURLE_OK || http_code != 200)
			printf("curl_easy_perform failed. curl_res = %d, Httpcode = %ld, curl_strerror = %s\n", curl_res, http_code, curl_easy_strerror(curl_res));
			return -4;
		 * Now, our receive_content.memory points to a memory block that is receive_content.size
		 * bytes big and contains the remote file.
		 * Do something nice with it!
	return 0;
int HttpRequest::sendReceiveEx(const char * url, RequestHandler * handler)
	int ret = 0;
	int httpCpde = 0;
	char receive[20480] = { 0 };
	unsigned int rlen = sizeof(receive);
	char requet[10240] = { 0 };
	if (0 != handler->request.getSize())
		sprintf(requet, "%s?%s#", url, handler->request.getData());
		sprintf(requet, "%s", url);
	if (receive_content.memory)
		free(receive_content.memory);
		receive_content.memory = NULL;
		receive_content.memory = (char*)malloc(1);
		receive_content.size = 0;
	if (curl_handle)
		// set params 
		curl_easy_reset(curl_handle);
		/* enable TCP keep-alive for this transfer */
		curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE, 1L);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_TCP_KEEPALIVE failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		/* keep-alive idle time to 120 seconds */
		curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPIDLE, 120L);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_TCP_KEEPIDLE failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		/* interval time between keep-alive probes: 30 seconds */
		curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPINTVL, 30L);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_TCP_KEEPINTVL failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		/* export cookies to this file when closing the handle */
		curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, "./cookies.txt");
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_COOKIEJAR failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		/* get cookies from an existing file */
		curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, "./cookies.txt");
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_COOKIEFILE failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		setResultCallback();
		setRequestTimeout(10);
		ret = setRequestUrl(url);
		if (0 != ret)
			return ret;
		setPostData((const char *)handler->request.getData(), handler->request.getSize());
		if (http_headers)
			curl_res = curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, http_headers);
			if (CURLE_OK != curl_res)
				printf("curl_easy_setopt CURLOPT_HTTPHEADER failed. curl_res = %d,  curl_strerror = %s", curl_res, curl_easy_strerror(curl_res));
				return -1;
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_NOPROGRESS failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_NOSIGNAL failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		curl_res = curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT_MS, 0);
		if (CURLE_OK != curl_res)
			printf("curl_easy_setopt CURLOPT_CONNECTTIMEOUT_MS failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			return -1;
		/* get it! */
		curl_res = curl_easy_perform(curl_handle);
		if (curl_res == CURLE_OPERATION_TIMEDOUT)
			int retry_count = retry_times;
			while (retry_count > 0)
				curl_res = curl_easy_perform(curl_handle);
				if (curl_res != CURLE_OPERATION_TIMEDOUT) break;
				retry_count--;
		if (curl_res == CURLE_OPERATION_TIMEDOUT)
			printf("curl_easy_perform failed. curl_res = %d,  curl_strerror = %s\n", curl_res, curl_easy_strerror(curl_res));
			ret = -3;
		http_code = 0;
		curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_code);
		if (curl_res == CURLE_OK && http_code == 200)
			 * Now, our receive_content.memory points to a memory block that is receive_content.size
			 * bytes big and contains the remote file.
			 * Do something nice with it!
			getContent(receive, &rlen);
			char *response = (char*)handler->response.resize(rlen, rlen + 4, false);
			memset(response, '\0', rlen+4);
			memcpy(response, receive, rlen);
			response[rlen] = '\0';
			httpCpde = getHttpCode();
			handler->http_code = httpCpde;
			printf("sendReceive() <<< Data : \n%s\n[response data len : %d]\n", handler->response.getData(), handler->response.getSize());
			ret = 0;
			printf("curl_easy_perform failed. curl_res = %d, Httpcode = %ld, curl_strerror = %s\n", curl_res, http_code, curl_easy_strerror(curl_res));
			return -4;
	return ret;
int HttpRequest::getHttpCode()
	return http_code;
int HttpRequest::getHeader(char *header, unsigned int *len)
	if (receive_header.size > *len)
		return -5;
	memcpy(header, receive_header.memory, receive_header.size);
	*len = receive_header.size;
	return 0;
int HttpRequest::getContent(char *content, unsigned int *len)
	if (receive_content.size > *len)
		return -5;
	memcpy(content, receive_content.memory, receive_content.size);
	*len = receive_content.size;
	return 0;
#include <stdio.h>
#include "httpConn.h"
// 封装自己的客户端
int customizeSendReceive(const char *url)
	int			ret = 0;
	HttpRequest req;
	int httpCpde = 0;
	char receive[204800] = { 0 };
	unsigned int rlen = sizeof(receive);
		int urlLen = strlen(url);
		if (0 >= urlLen)
			break;
		ret = req.setRequestUrl(url);
		if (0 != ret)
			break;
		ret = req.performRequest();
		if (0 != ret)
			break;
		httpCpde = req.getHttpCode();
		ret = req.getContent(receive, &rlen);
		if (0 != ret)
			break;
	} while (0);
	if (0 == ret && 200 == httpCpde)
		printf("ReceivevData :");
		for (int i = 0; i < rlen; i++)
			printf("%c", receive[i]);
		printf("\n");
		printf("sendReceive() failed.\n");
	return ret;
// 使用httpClient已经实现的客户端
void testSys(const char *url, const char *post_data)
	HttpRequest		m_Conn;	
	RequestHandler  handler;
	handler.request.resize(0);
	handler.response.resize(0);
	int rlen = strlen(data);
	char *request = (char*)handler->request.resize(rlen, rlen + 4, false);
	memset(request, '\0', rlen+4);
	memcpy(request, post_data, rlen);
	int ret = m_Conn.sendReceiveEx(url, &handler);
	if (0 != ret)
		printf("sendReceiveEx failed, ret = %d\n", ret);
		printf("response data : %s\n", (char *)handler.response.getData());
int main(int argc, char *argv[])
	//customizeSendReceive("www.xxx.com?xxxxxx#");
	//testSys("www.xxx.com", "?...#");
	return 0;
                    前面的文章《Libcurl编译指南——Android和Windows系统》已经就libcurl在Windows和Android系统编做了详细的说明。本文档用C/C++实现简单的HTTP/HTTPS客户端,支持get和post,支持保持session和长连接。httpConn.h#ifndef __HTTP_CONN_H__#define __HTTP_CONN_H__#include ...
 
推荐文章