C++ Post/Get请求(Boost.Asio库)

引言

http协议是互联网上应用最为广泛的一种网络协议,他在接口中扮演着重要的角色,Post/Get请求,想必大家都有所耳闻,我们一起利用Boost::Asio库来实现Post/Get请求的发送。

 

 

注意:本篇代码没有直接引用boost等命名空间,为的是新入门Boost的同学能够更好的了解每个参数在boost的具体命名空间位置,有助于更好的理解boost的布局。
 
版权所有:CSND_Ayo ,转载请注明出处: http://blog.csdn.net/csnd_ayo
 

 

简介

Boost库版本:1.61.0

http请求:想必大家早已经耳濡目染,我这里就不做太多赘述,附上一个图片,以便大家加深印象。

 

下载


我封装了下,含代码,样例程序,动态库,资源下载地址:http://download.csdn.net/detail/csnd_ayo/9792036

BOOST库1.63:https://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.zip/download

赏析

暂无
 

源码

完成这个实现分别建立了2个类来解决这个实现。

HttpBase,HttpBoost。以达到抽象的效果。

http_mark.h 错误宏

example.cpp 示例调用文件

post 请求发送方式: 协议url[表数据]

get 请求发送方式:协议url

 

http_mark.h

 

#ifndef __CLY_HTTP_MARK_H__
#define __CLY_HTTP_MARK_H__


#define HTTP_SUCCESS       (0)          // 操作成功
#define HTTP_ERROR_UNKNOWN      (-1)         // 未知的错误
#define HTTP_ERROR_NETWORK      (-2)         // 网络连接失败
#define HTTP_ERROR_HTTP_HEAD    (-3)         // 未找到协议头 http || https 

#define HTTP_ERROR_SERVICE      (-1000)      // 服务器请求失败
#define HTTP_ERROR_LOGIN        (-1001)      // 登录失败
#define HTTP_ERROR_ID           (-1002)      // 企业ID错误
#define HTTP_ERROR_USER         (-1003)      // 帐号不存在
#define HTTP_ERROR_PASSWORD     (-1004)      // 密码错误



#endif // __CLY_HTTP_MARK_H__

 

 

 

 

 

 

HttpBase.h

 

/*
* 简介:利用Boost发送http的Post/Get请求
* 作者:Louie
* 邮箱:727057301@qq.com
* CSDN:http://blog.csdn.net/csnd_ayo
* 码云:https://git.oschina.net/Mr_ChenLuYong
* github:http://github.com/chenluyong
* 创建时间:2017年3月12日 04:32:07
* VS版本:VS2013
* Boost版本:boost_1_61_0
*/

#ifndef __CLY_HTTPBASE_H__
#define __CLY_HTTPBASE_H__

#include <iostream>

using namespace std;
namespace cly {

class HttpBase {

public:

	HttpBase();

	virtual ~HttpBase();

	/*
	* 发送Post请求
	*/
	virtual int post(const std::string& url) = 0;

	/*
	* 发送get请求
	*/
	virtual int get(const std::string& url) = 0;

	virtual std::string getResponse(void) = 0;

protected:
	typedef int(*pBuildRequest)(const string&, const string&,
		std::ostream&);

	/*
	* 解析URL
	* parseUrl
	* url: 待解析的URL
	* out_server: 服务器名
	* out_port: 端口号
	* out_path: 服务器子页
	*/
	static int parseUrl(const std::string& url, std::string& out_server,
		std::string& out_port, std::string& out_path);

	/*
	* 建立Post请求
	* buildPostRequest
	*/
	static int buildPostRequest(const std::string& server, const std::string& path,
					std::ostream& out_request);

	/*
	* 建立Get请求
	* buildGetRequest
	*/
	static int buildGetRequest(const std::string& server, const std::string& path,
					std::ostream& out_request);

};

}

#endif // __CLY_HTTPBASE_H__

 

 

 

 

 

HttpBase.cpp

 

/*
* 简介:利用Boost发送http的Post/Get请求
* 作者:Louie
* 邮箱:727057301@qq.com
* CSDN:http://blog.csdn.net/csnd_ayo
* 码云:https://git.oschina.net/Mr_ChenLuYong
* github:http://github.com/chenluyong
* 创建时间:2017年3月12日 04:32:07
* VS版本:VS2013
* Boost版本:boost_1_61_0
*/

#include "HttpBase.h"
#include "http_mark.h"

#define HTTP_JSON_BEGIN ("[")
#define HTTP_JSON_END ("]")
using namespace cly;
cly::HttpBase::HttpBase() {
}


cly::HttpBase::~HttpBase() {
}

//
//可以解析下列三种类型的URL:
//http://yunhq.sse.com.cn:32041/v1/sh1/snap/204001?callback=jQuery_test&select=name%2Clast%2Cchg_rate%2Cchange%2Camount%2Cvolume%2Copen%2Cprev_close%2Cask%2Cbid%2Chigh%2Clow%2Ctradephase
//http://hq.sinajs.cn/list=sh204001
//https://www.baidu.com
//
int cly::HttpBase::parseUrl(const std::string& url, std::string& out_server,
	std::string& out_port, std::string& out_path) {
	const std::string& http___ = "http://";
	const std::string& https___ = "https://";
	std::string temp_data = url;

	// 截断http协议头
	if (temp_data.find(http___) == 0) {
		temp_data = temp_data.substr(http___.length());
	}
	else if (temp_data.find(https___) == 0) {
		temp_data = temp_data.substr(https___.length());
	}
	else {
		return HTTP_ERROR_HTTP_HEAD;
	}

	// 解析域名
	std::size_t idx = temp_data.find('/');
	// 解析 域名后的page
	if (std::string::npos == idx) {
		out_path = "/";
		idx = temp_data.size();
	}
	else {
		out_path = temp_data.substr(idx);
	}

	// 解析域名
	out_server = temp_data.substr(0, idx);

	// 解析端口
	idx = out_server.find(':');
	if (std::string::npos == idx) {
		out_port = "80";
	}
	else {
		out_port = out_server.substr(idx + 1);
		out_server = out_server.substr(0, idx);
	}

	return HTTP_SUCCESS;
}



/*
* 建立Post请求
* buildPostRequest
*/
int cly::HttpBase::buildPostRequest(const std::string& server, const std::string& path,
	std::ostream& out_request) {
	// 分割path中的json数据
	std::string temp_path(path), temp_json;
	int json_pos_begin = temp_path.find(HTTP_JSON_BEGIN) + 1;
	int json_pos_end = temp_path.find(HTTP_JSON_END);
	if (json_pos_begin != std::string::npos) {
		// 计算json的长度
		int temp_json_lenth = std::string::npos;
		if (json_pos_end != temp_json_lenth) {
			temp_json_lenth = (json_pos_end - json_pos_begin);
		}
		temp_json = temp_path.substr(json_pos_begin, temp_json_lenth);
		temp_path = temp_path.substr(0, (json_pos_begin - 1));
	}


	out_request << "POST " << temp_path.c_str() << " HTTP/1.0\r\n";
	out_request << "Host: " << server.c_str() << "\r\n"; 
	out_request << "Content-Length: " << temp_json.length() << "\r\n";
	out_request << "Content-Type: application/x-www-form-urlencoded\r\n";
	out_request << "Accept: */*\r\n";
	out_request << "Connection: close\r\n\r\n";
	out_request << temp_json.c_str();
	return HTTP_SUCCESS;
}

/*
* 建立Get请求
* buildGetRequest
*/
int cly::HttpBase::buildGetRequest(const std::string& server, const std::string& path,
	std::ostream& out_request) {
	out_request << "GET " << path.c_str() << " HTTP/1.0\r\n";
	out_request << "Host: " << server.c_str() << "\r\n";
	out_request << "Accept: */*\r\n";
	out_request << "Connection: close\r\n\r\n";
	return HTTP_SUCCESS;
}

 

 

 

 

 

HttpBoost.h

 

/*
* 简介:利用Boost发送http的Post/Get请求
* 作者:Louie
* 邮箱:727057301@qq.com
* CSDN:http://blog.csdn.net/csnd_ayo
* 码云:https://git.oschina.net/Mr_ChenLuYong
* github:http://github.com/chenluyong
* 创建时间:2017年3月12日 04:32:07
* VS版本:VS2013
* Boost版本:boost_1_61_0
*/

#ifndef __CLY_HTTPBOOST_H__
#define __CLY_HTTPBOOST_H__

#include "HttpBase.h"

#include <boost/asio.hpp>

namespace cly {

class HttpBoost :
	public HttpBase {

public:

	HttpBoost(boost::asio::io_service& io_service);

	virtual ~HttpBoost();

	/*
	* 发送Post请求
	*/
	virtual int post(const std::string& url);

	/*
	* 发送get请求
	*/
	virtual int get(const std::string& url);

	virtual std::string getResponse(void) {
		return responseData_;
	}
	
private:
	// 建立请求
	void handle_request_resolve(const std::string& url, pBuildRequest func);

	// 解析后
	void handle_resolve(const boost::system::error_code& err,
		boost::asio::ip::tcp::resolver::iterator endpoint_iterator);

	// 连接后
	void handle_connect(const boost::system::error_code& err);

	// 发送请求后
	void handle_write_request(const boost::system::error_code& err);
	
	// 读取响应后
	void handle_read_status_line(const boost::system::error_code& err);
	
	// 读取响应头后
	void handle_read_headers(const boost::system::error_code& err);

	// 读取正文数据后
	void handle_read_content(const boost::system::error_code& err);
private:

	// 解析器
	boost::asio::ip::tcp::resolver resolver_;
	// 套接字
	boost::asio::ip::tcp::socket socket_;
	// 请求缓冲区
	boost::asio::streambuf request_;
	// 响应缓冲区
	boost::asio::streambuf response_;
	// 响应数据
	std::string responseData_;

};
// Post请求 消息范例 url:80/openapi/getversion[Post请求数据表格]
std::string post(std::string url);



std::string get(std::string url);


}
#endif // __CLY_HTTPBOOST_H__

 

 

 

 

 

HttpBoost.cpp

 

/*
* 简介:利用Boost发送http的Post/Get请求
* 作者:Louie
* 邮箱:727057301@qq.com
* CSDN:http://blog.csdn.net/csnd_ayo
* 码云:https://git.oschina.net/Mr_ChenLuYong
* github:http://github.com/chenluyong
* 创建时间:2017年3月12日 04:32:07
* VS版本:VS2013
* Boost版本:boost_1_61_0
*/

#include "HttpBoost.h"
using namespace cly;
#include <boost/bind.hpp>

#include "http_mark.h"

cly::HttpBoost::HttpBoost(boost::asio::io_service& io_service)
: resolver_(io_service), socket_(io_service) {
}


cly::HttpBoost::~HttpBoost() {
}


int cly::HttpBoost::post(const std::string& url) {
	handle_request_resolve(url, HttpBase::buildPostRequest);
	return HTTP_SUCCESS;
}


int cly::HttpBoost::get(const std::string& url) {
	handle_request_resolve(url, HttpBase::buildGetRequest);
	return HTTP_SUCCESS;
}


void cly::HttpBoost::handle_request_resolve(const std::string& url, pBuildRequest func) {
	try {
		responseData_.clear();
		// 解析URL
		std::string server, port, path;
		parseUrl(url, server, port, path);

		std::ostream request_stream(&request_);

		// 合成请求
		func(server, path, request_stream);

		// 解析服务地址\端口
		boost::asio::ip::tcp::resolver::query query(server, port);
		resolver_.async_resolve(query,
			boost::bind(&cly::HttpBoost::handle_resolve, this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::iterator));
	}
	catch (std::exception& e) {
		socket_.close();
		std::cout << "Exception: " << e.what() << "\n";
	}	
	return;
}


void cly::HttpBoost::handle_resolve(const boost::system::error_code& err,
	boost::asio::ip::tcp::resolver::iterator endpoint_iterator) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}

	// 尝试连接
	boost::asio::async_connect(socket_, endpoint_iterator,
		boost::bind(&cly::HttpBoost::handle_connect, this,
		boost::asio::placeholders::error));
}


void cly::HttpBoost::handle_connect(const boost::system::error_code& err) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}

	// 发送request请求
	boost::asio::async_write(socket_, request_,
		boost::bind(&cly::HttpBoost::handle_write_request, this,
		boost::asio::placeholders::error));
}


void cly::HttpBoost::handle_write_request(const boost::system::error_code& err) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}

	// 异步持续读数据到response_,直到接收协议符号 \r\n 为止
	boost::asio::async_read_until(socket_, response_, "\r\n",
		boost::bind(&cly::HttpBoost::handle_read_status_line, this,
		boost::asio::placeholders::error));
}


void cly::HttpBoost::handle_read_status_line(const boost::system::error_code& err) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}

	// 解析buff
	std::istream response_stream(&response_);
	unsigned int status_code;
	std::string http_version, status_message;
	response_stream >> http_version;
	response_stream >> status_code;
	std::getline(response_stream, status_message);

	// 核对是否是正确返回
	if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
		std::cout << "错误的响应数据\n";
		return;
	}
	if (status_code != 200) {
		std::cout << "服务器响应的状态码: " << status_code << "\n";
		return;
	}

	// 读取响应头,直到接收协议符号 \r\n\r\n 为止
	boost::asio::async_read_until(socket_, response_, "\r\n\r\n",
		boost::bind(&cly::HttpBoost::handle_read_headers, this,
		boost::asio::placeholders::error));
}


void cly::HttpBoost::handle_read_headers(const boost::system::error_code& err) {
	if (err) {
		std::cout << "Error: " << err << "\n";
		return;
	}
	// 输出响应头
	std::istream response_stream(&response_);
	std::string header;
	while (std::getline(response_stream, header) && header != "\r") {
#ifdef _DEBUG
		std::cout << header << "\n";
#endif 
	}
#ifdef _DEBUG
	std::cout << "\n";
#endif 

	// 写完所有剩余的内容
	if (response_.size() > 0) {
		boost::asio::streambuf::const_buffers_type cbt = response_.data();
		responseData_ += std::string(boost::asio::buffers_begin(cbt), boost::asio::buffers_end(cbt));
#ifdef _DEBUG
		std::cout << &response_;
#endif 
	}

	// 开始读取剩余所有内容
	boost::asio::async_read(socket_, response_,
		boost::asio::transfer_at_least(1),
		boost::bind(&cly::HttpBoost::handle_read_content, this,
		boost::asio::placeholders::error));
}

void cly::HttpBoost::handle_read_content(const boost::system::error_code& err) {
	if (!err) {
		// 输出读到的数据
		boost::asio::streambuf::const_buffers_type cbt = response_.data();
		responseData_ += std::string(boost::asio::buffers_begin(cbt), boost::asio::buffers_end(cbt));
#ifdef _DEBUG
		std::cout << &response_;
#endif 

		// 继续读取剩余内容,直到读到EOF
		boost::asio::async_read(socket_, response_,
			boost::asio::transfer_at_least(1),
			boost::bind(&cly::HttpBoost::handle_read_content, this,
			boost::asio::placeholders::error));
	}
	else if (err != boost::asio::error::eof) {
		std::cout << "Error: " << err << "\n";
	}
	else {
		socket_.close();
		resolver_.cancel();
		std::cout << "读取响应数据完毕." << std::endl;
	}
}


std::string cly::post(std::string url) {
	boost::asio::io_service io;
	cly::HttpBoost c(io);
	c.post(url);
	io.run();
	return c.getResponse();
}

std::string cly::get(std::string url) {
	boost::asio::io_service io;
	cly::HttpBoost c(io);
	c.get(url);
	io.run();
	return c.getResponse();
}

 

example.cpp

 

#include <iostream>
#include "HttpBoost.h"

int main() {
	std::string str("http://yunhq.sse.com.cn:32041/v1/sh1/snap/204001?callback=jQuery_test&select=name%2Clast%2Cchg_rate%2Cchange%2Camount%2Cvolume%2Copen%2Cprev_close%2Cask%2Cbid%2Chigh%2Clow%2Ctradephase");
	str = cly::get(str);
	std::cout << str.c_str() << std::endl;

	str = "http://service.winic.org:8009/sys_port/gateway/[id=13695800360&pwd=13645411460&to=13695800360&content=infomation&time=]";
	str = cly::post(str);
	std::cout << str.c_str() << std::endl;
	
	return 0;
}

 

 

 

 

 

 

 

 

代码中理论上是跨平台的。
 

详解

评论超过5个,我便会修改该文章,对整体思路进行梳理讲解。
  • 17
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值