纯C++实现的HTTP请求

Home / C++ 百晓生 2018-7-12 6987

纯C++实现的HTTP请求(POST/GET),支持windows和linux, 进行简单的封装, 方便调用。实现如下:

.h文件

#pragma once
typedef size_t (*pfn_write_data)(char *buffer,size_t size, size_t nitems,void *pattach);
//优点:不需要依赖第三方库,缺点:功能单一如:不支持301跳转
class CHttpConnect
{
public:
	CHttpConnect();
	~CHttpConnect(void);
	static string HttpPost(std::string host, std::string post);
	static string HttpGet(std::string host);
	static void HttpDownload(std::string host,pfn_write_data pwrite_data,void* pattach=NULL);
private:
	static short ParseUrl(std::string& host,std::string& path);
	static string SocketHttp(std::string host, std::string request,short port,pfn_write_data pwrite_data=NULL,void* pattach=NULL);
};

.cpp文件

#include "StdAfx.h"
#include "HttpConnect.h"
#include <WinSock.h>
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <algorithm>
#ifdef WIN32
#pragma comment(lib,"ws2_32.lib")
#endif
CHttpConnect::CHttpConnect()
{
}
CHttpConnect::~CHttpConnect(void)
{
}
short CHttpConnect::ParseUrl(std::string& host,std::string& path)
{
	short nPort = 80;
	//处理主机域名不能带http开头
	int pos = host.find("http://");
	if (pos >= 0)
	{
		int endPos = host.find("/",pos + 7);
		if(endPos >= 0)
		{
			path = host.substr(endPos,host.length() - endPos);
			host = host.substr(pos + 7,endPos - pos - 7);
		}
		else
		{
			host = host.substr(pos + 7,host.length() - pos - 7);
		}
		pos = host.find(":");
		if (pos >= 0)
		{
			string sPort = host.substr(pos + 1,host.length() - pos - 1);
			nPort = atoi(sPort.c_str());
			host = host.substr(0,pos);
		}
	}
	else
	{
		int endPos = host.find("/");
		if(endPos >= 0)
		{
			path = host.substr(endPos,host.length() - endPos);
			host = host.substr(0,endPos);
		}
		pos = host.find(":");
		if (pos >= 0)
		{
			string sPort = host.substr(pos + 1,host.length() - pos - 1);
			nPort = atoi(sPort.c_str());
			host = host.substr(0,pos);
		}
	}
	return nPort;
}
std::string CHttpConnect::SocketHttp(std::string host, std::string request,short port,pfn_write_data pwrite_data,void* pattach)
{
#ifdef WIN32
	//此处一定要初始化一下,否则gethostbyname返回一直为空
	WSADATA wsa = { 0 };
	WSAStartup(MAKEWORD(2, 2), &wsa);
#endif
	int sockfd;
	struct sockaddr_in address;
	struct hostent *server;
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	address.sin_family = AF_INET;
	address.sin_port = htons(port);
	server = gethostbyname(host.c_str());
	memcpy((char *)&address.sin_addr.s_addr,(char*)server->h_addr, server->h_length);
	if(-1 == connect(sockfd,(struct sockaddr *)&address,sizeof(address))){
		ASSERT("连接失败");
		return "";
	}
#ifdef WIN32
	send(sockfd, request.c_str(),request.size(),0);
#else
	write(sockfd,request.c_str(),request.size());
#endif
	char buf[1024];
	int actual = -1;
	bool checkHttpHead = true;
	LPCSTR lpLine = NULL;
	std::stringstream out;
#ifdef WIN32
	while(actual = recv(sockfd, buf, 1024,0))
#else
	while(actual = read(sockfd, buf, 1024))
#endif
	{
		if (checkHttpHead)
		{
			if ((lpLine = strstr(buf,"\r\n\r\n")))
			{
				int offset = lpLine - buf + strlen("\r\n\r\n");//出现的指针减去起始指针得到长度
				if(pwrite_data == NULL)
					out << string(buf+offset,actual-offset) << endl;//数据写到缓存
				else
					pwrite_data(buf+offset,1,actual-offset,pattach);
				checkHttpHead = false;//http头读取完毕
				lpLine = NULL;//指针放空
			}
			continue;
		}
		if(pwrite_data == NULL)
			out << string(buf,actual) << endl;//数据写到缓存
		else
			pwrite_data(buf,1,actual,pattach);
	}
#ifdef WIN32
	closesocket(sockfd);
	//此处一定要初始化一下,否则gethostbyname返回一直为空
	::WSACleanup();
#else
	close(sockfd);
#endif
	string str_result = out.str();
	return str_result;
}
std::string CHttpConnect::HttpPost(std::string host, std::string post)
{
	string path;
	short nPort = ParseUrl(host,path);
	//POST请求方式
	std::stringstream stream;
	stream << "POST " << path;
	stream << " HTTP/1.0\r\n";
	stream << "Host: "<< host << "\r\n";
	stream << "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
	stream << "Content-Type:application/x-www-form-urlencoded\r\n";
	stream << "Content-Length:" << post.length()<<"\r\n";
	stream << "Connection:close\r\n\r\n";
	stream << post.c_str();
	return SocketHttp(host, stream.str(),nPort);
}
std::string CHttpConnect::HttpGet(std::string host)
{
	//GET请求方式
	std::stringstream stream;
	string path;
	short nPort = ParseUrl(host,path);
	stream << "GET " << path;
	stream << " HTTP/1.0\r\n";
	stream << "Host: " << host << "\r\n";
	stream <<"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
	stream <<"Connection:close\r\n\r\n";
	return SocketHttp(host, stream.str(),nPort);
}
void CHttpConnect::HttpDownload(std::string host,pfn_write_data pwrite_data,void* pattach)
{
	//GET请求方式
	std::stringstream stream;
	string path;
	short nPort = ParseUrl(host,path);
	stream << "GET " << path;
	stream << " HTTP/1.0\r\n";
	stream << "Host: " << host << "\r\n";
	stream <<"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
	stream <<"Connection:close\r\n\r\n";
	SocketHttp(host, stream.str(),nPort,pwrite_data,pattach);
}


调用方法:

本文链接:https://www.it72.com/12392.htm

推荐阅读
最新回复 (0)
返回