标签:
项目接近阶段性尾声了,又要去做另一个项目的框架,真是完全忙不过来。。。
整理项目过程中,为了减少第三方库的使用,我使用boost的asio封装了http请求
1 #pragma once 2 3 #include <string> 4 #include <vector> 5 #include <iostream> 6 #include <boost/asio.hpp> 7 #include <boost/enable_shared_from_this.hpp> 8 9 struct header 10 { 11 std::string name; 12 std::string value; 13 }; 14 15 struct msg_request 16 { 17 public: 18 explicit msg_request(){ clear();} 19 20 std::string method; // "GET", "POST". 21 std::string uri; // 不包含http://的路径 22 int http_version_major; // 23 int http_version_minor; // 24 std::vector<header> headers;// HTTP包头 25 std::string content; // 上传的数据 26 std::string spath; // 请求地址 27 28 void clear() 29 { 30 method = "GET"; 31 uri.clear(); 32 http_version_major = 1; 33 http_version_minor = 0; 34 headers.clear(); 35 content.clear(); 36 spath.clear(); 37 38 } 39 }; 40 41 struct msg_response 42 { 43 public: 44 explicit msg_response(){ clear();} 45 std::string http_version; // 版本 46 int32_t status_code; // 状态码 47 std::string status_message; // 状态 48 std::vector<header> headers; // HTTP包头 49 std::stringstream content; // HTTP返回的内容 50 51 void clear() 52 { 53 http_version.clear(); 54 status_code = -1; 55 status_message.clear(); 56 headers.clear(); 57 content.str(""); 58 } 59 }; 60 61 class peer_http: public boost::enable_shared_from_this<peer_http> 62 { 63 public: 64 peer_http(boost::asio::io_service& io_service); 65 virtual ~peer_http(); 66 67 void post_request(const msg_request& req); 68 //同步处理才使用 69 virtual void on_complete(){}; 70 private: 71 void handle_resolve(const boost::system::error_code& err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator); 72 void handle_connect(const boost::system::error_code& err); 73 void handle_write_request(const boost::system::error_code& err); 74 void handle_read_status_line(const boost::system::error_code& err); 75 void handle_read_headers(const boost::system::error_code& err); 76 void handle_read_content(const boost::system::error_code& err); 77 78 private: 79 boost::asio::ip::tcp::resolver resolver_; 80 boost::asio::ip::tcp::socket socket_; 81 boost::asio::streambuf request_; 82 boost::asio::streambuf response_; 83 84 protected: 85 //http结果回调接口 (异步非线程安全) 86 virtual void http_response(bool result, const std::string& response) = 0; 87 88 //同步处理 使用peer_http_mgr从on_complete处理 89 void use_synchronization(); 90 msg_response m_response; 91 };
1 #include "stdafx.h" 2 #include "peer_http.h" 3 #include <boost/bind.hpp> 4 #include <boost/lexical_cast.hpp> 5 #include <boost/algorithm/string.hpp> 6 7 using namespace boost; 8 using namespace boost::asio::ip; 9 10 peer_http::peer_http(boost::asio::io_service& io_service) 11 : resolver_(io_service), 12 socket_(io_service) 13 { 14 } 15 16 peer_http::~peer_http() 17 { 18 if(socket_.is_open()) 19 { 20 boost::system::error_code ec; 21 socket_.close(ec); 22 } 23 } 24 25 void peer_http::post_request(const msg_request& req) 26 { 27 std::ostream request_stream(&request_); 28 if (req.method == "GET") 29 { 30 request_stream << req.method <<" "<< req.spath << " HTTP/"<< req.http_version_major<<"."<<req.http_version_minor<<"\r\n"; 31 request_stream << "Host: " << req.uri << "\r\n\r\n"; 32 } 33 else if (req.method == "POST") 34 { 35 request_stream << req.method <<" "<< req.spath << " HTTP/"<< req.http_version_major<<"."<<req.http_version_minor<<"\r\n"; 36 request_stream << "Host: " << req.uri << "\r\n"; 37 request_stream << req.headers[1].name << ": "<<req.headers[1].value <<"\r\n"; 38 request_stream << req.headers[0].name << ": "<<req.headers[0].value <<"\r\n\r\n"; 39 request_stream << req.content << "\r\n\r\n"; 40 } 41 42 request_stream << "Accept: */*\r\n"; 43 //request_stream << "Pragma: no-cache\r\n"; 44 //request_stream << "Cache-Control: no-cache\r\n"; 45 request_stream << "Connection: close\r\n"; 46 47 // Start an asynchronous resolve to translate the server and service names 48 // into a list of endpoints. 49 std::string szService ("http"); 50 std::string szIp = req.uri; 51 int i = req.uri.find(":") ; 52 if (i != -1) 53 { 54 szService = req.uri.substr(i+1); 55 szIp = req.uri.substr(0, i); 56 } 57 58 m_response.clear(); 59 60 // Get a list of endpoints corresponding to the server name. 61 tcp::resolver::query query(szIp, szService); 62 resolver_.async_resolve(query, 63 boost::bind(&peer_http::handle_resolve, shared_from_this(), 64 boost::asio::placeholders::error, 65 boost::asio::placeholders::iterator)); 66 } 67 68 void peer_http::handle_resolve(const boost::system::error_code& err, 69 tcp::resolver::iterator endpoint_iterator) 70 { 71 if (!err) 72 { 73 // Attempt a connection to each endpoint in the list until we 74 // successfully establish a connection. 75 boost::asio::async_connect(socket_, endpoint_iterator, 76 boost::bind(&peer_http::handle_connect, shared_from_this(), 77 boost::asio::placeholders::error)); 78 } 79 else 80 { 81 http_response(false, err.message()); 82 } 83 } 84 85 void peer_http::handle_connect(const boost::system::error_code& err) 86 { 87 if (!err) 88 { 89 // The connection was successful. Send the request. 90 boost::asio::async_write(socket_, request_, 91 boost::bind(&peer_http::handle_write_request, shared_from_this(), 92 boost::asio::placeholders::error)); 93 } 94 else 95 { 96 http_response(false, err.message()); 97 } 98 } 99 100 void peer_http::handle_write_request(const boost::system::error_code& err) 101 { 102 if (!err) 103 { 104 // Read the response status line. The response_ streambuf will 105 // automatically grow to accommodate the entire line. The growth may be 106 // limited by passing a maximum size to the streambuf constructor. 107 boost::asio::async_read_until(socket_, response_, "\r\n", 108 boost::bind(&peer_http::handle_read_status_line, shared_from_this(), 109 boost::asio::placeholders::error)); 110 } 111 else 112 { 113 http_response(false, err.message()); 114 } 115 } 116 117 void peer_http::handle_read_status_line(const boost::system::error_code& err) 118 { 119 if (!err) 120 { 121 // Check that response is OK. 122 std::istream response_stream(&response_); 123 response_stream >> m_response.http_version; 124 response_stream >> m_response.status_code; 125 std::getline(response_stream, m_response.status_message); 126 boost::trim(m_response.status_message); 127 if (!response_stream || m_response.http_version.substr(0, 5) != "HTTP/") 128 { 129 http_response(false, "Invalid response\n"); 130 return; 131 } 132 if (m_response.status_code != 200) 133 { 134 std::string ret = "Response returned with status code " + lexical_cast<std::string>(m_response.status_code) ; 135 http_response(false, ret); 136 return; 137 } 138 139 // Read the response headers, which are terminated by a blank line. 140 boost::asio::async_read_until(socket_, response_, "\r\n\r\n", 141 boost::bind(&peer_http::handle_read_headers, shared_from_this(), 142 boost::asio::placeholders::error)); 143 } 144 else 145 { 146 http_response(false, err.message()); 147 } 148 } 149 150 void peer_http::handle_read_headers(const boost::system::error_code& err) 151 { 152 if (!err) 153 { 154 // Process the response headers. 155 std::istream response_stream(&response_); 156 157 std::string strLine; 158 while (std::getline(response_stream, strLine) && strLine != "\r") 159 { 160 header h; 161 h.name = strLine.substr(0, strLine.find_first_of(":")); 162 h.value = strLine.substr(h.name.size()+1, strLine.find_first_of("\r")); 163 boost::trim(h.value); 164 m_response.headers.push_back(h); 165 } 166 167 // Write whatever content we already have to output. 168 if (response_.size() > 0) 169 { 170 m_response.content << &response_; 171 } 172 173 // Start reading remaining data until EOF. 174 boost::asio::async_read(socket_, response_, 175 boost::asio::transfer_at_least(1), 176 boost::bind(&peer_http::handle_read_content, shared_from_this(), 177 boost::asio::placeholders::error)); 178 } 179 else 180 { 181 http_response(false, err.message()); 182 } 183 } 184 185 void peer_http::handle_read_content(const boost::system::error_code& err) 186 { 187 if (!err) 188 { 189 // Write all of the data that has been read so far. 190 m_response.content << &response_; 191 192 // Continue reading remaining data until EOF. 193 boost::asio::async_read(socket_, response_, 194 boost::asio::transfer_at_least(1), 195 boost::bind(&peer_http::handle_read_content, shared_from_this(), 196 boost::asio::placeholders::error)); 197 } 198 else if (err != boost::asio::error::eof) 199 { 200 http_response(false, err.message()); 201 } 202 else 203 { 204 http_response(true, m_response.content.str()); 205 } 206 } 207 208 #include <net/peer_http_mgr.h> 209 void peer_http::use_synchronization() 210 { 211 peer_http_mgr::instance().postTask(shared_from_this()); 212 }
1 #pragma once 2 #include <enable_queue.h> 3 #include <enable_singleton.h> 4 #include <enable_smart_ptr.h> 5 6 class peer_http; 7 class peer_http_mgr: 8 public enable_singleton<peer_http_mgr> 9 { 10 public: 11 peer_http_mgr(); 12 virtual ~peer_http_mgr(); 13 14 void postTask(boost::shared_ptr<peer_http> task); 15 void update(double elapsed); 16 17 private: 18 fast_safe_queue<boost::shared_ptr<peer_http>> m_complate_queue; 19 };
1 #include "stdafx.h" 2 #include "peer_http_mgr.h" 3 #include <net\peer_http.h> 4 5 peer_http_mgr::peer_http_mgr() 6 { 7 } 8 9 peer_http_mgr::~peer_http_mgr() 10 { 11 } 12 13 void peer_http_mgr::postTask(boost::shared_ptr<peer_http> task) 14 { 15 m_complate_queue.push(task); 16 } 17 void peer_http_mgr::update(double elapsed) 18 { 19 boost::shared_ptr<peer_http> task; 20 while (!m_complate_queue.empty()) 21 { 22 if(m_complate_queue.pop(task)) 23 task->on_complete(); 24 } 25 }
标签:
原文地址:http://www.cnblogs.com/zhangchengxin/p/4624210.html