Http请求通过线程添加超时处理

来源:互联网 发布:工程量预算软件 编辑:程序博客网 时间:2024/06/07 10:51

解决问题:

1.通过boost库asio去发送Http post请求,本文采用官方的同步调用方式(http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/http/client/sync_client.cpp

2.因为socket读写可能会堵塞,如Server迟迟没有返回,此时需要设置timeout来中断本次处理,

 因而采用新建线程HttpClient::wait_timeout来解决此问题,

3.LOGGER_DEBUG输出请自行修改

4.调用方式如下:

std::string ip ="172.16.17.58";

std::string port = "8181";

std::string path = "/login/";

std::string http_req_body = "user_name=tx02&password=e10adc3949ba59abbe56e057f20f8888";

HttpClient client(ip, port, path, http_req_body);

if(0 == client.post())

{

std::string response = client.getResponse()

......

}


代码如下:

1. HttpClient.h

#ifndef _HTTPCLIENT_H_#define _HTTPCLIENT_H_#include <string>#include "logger.h"#include <boost/asio.hpp>#include "boost/thread/mutex.hpp"#include "boost/thread/condition_variable.hpp"using boost::asio::ip::tcp;class HttpClient{public:HttpClient(const std::string&ip, const std::string&port);HttpClient(const std::string&ip, const std::string&port, const std::string&path,const std::string&content);~HttpClient(void);public:std::string setUrl(const std::string& path){path_ = path;};std::string setContent(const std::string& content){content_ = content;};std::string getResponse(){return body_;};int post();private:std::string getValidJson(const std::string& response);void wait_timeout(tcp::socket *socket);void incrementAliveThread();void decrementAliveThread();void interruptThread();private:std::string ip_;std::string port_;std::string path_;std::string content_;std::string body_;boost::mutex mu_; boost::condition_variable_any cond_; int alive_thread_count;};#endif // _HTTPCLIENT_H_
2. HttpClient.cpp

#include "httpclient.h"#include <iostream>#include <istream>#include <ostream>#include <string>#include <boost/property_tree/ptree.hpp>#include <boost/property_tree/json_parser.hpp>#include <boost/thread.hpp> #include <boost/bind.hpp>#include <boost/function/function0.hpp>HttpClient::HttpClient(const std::string&ip, const std::string&port):ip_(ip),port_(port){alive_thread_count = 0;}HttpClient::HttpClient(const std::string&ip, const std::string&port, const std::string&path,const std::string&content):ip_(ip),port_(port),path_(path),content_(content){alive_thread_count = 0;}HttpClient::~HttpClient(void){}void HttpClient::incrementAliveThread(){boost::mutex::scoped_lock lock(mu_); alive_thread_count++;LOGGER_DEBUG("incrementAliveThread " << alive_thread_count);}void HttpClient::decrementAliveThread(){boost::mutex::scoped_lock lock(mu_); alive_thread_count--;LOGGER_DEBUG("decrementAliveThread " << alive_thread_count);}void HttpClient::interruptThread(){while(alive_thread_count){LOGGER_DEBUG("Force the thread finish");boost::mutex::scoped_lock lock(mu_); cond_.notify_all(); boost::this_thread::sleep(boost::posix_time::milliseconds(5)); }}void HttpClient::wait_timeout(tcp::socket *socket) { {boost::mutex::scoped_lock lock(mu_); if (cond_.timed_wait(lock, boost::get_system_time() + boost::posix_time::seconds(10)))   {  LOGGER_DEBUG("recieved notification!");  } else {  LOGGER_ERROR("timeout, didn't recieve notification!");   socket->close();}}decrementAliveThread();}int HttpClient::post(){try{int ret = 0;alive_thread_count = 0;// Get a list of endpoints corresponding to the server name.boost::asio::io_service io_service;tcp::resolver resolver(io_service);tcp::resolver::query query(ip_, port_);tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);// Try each endpoint until we successfully establish a connection.tcp::socket socket(io_service);boost::asio::connect(socket, endpoint_iterator);// Form the request. We specify the "Connection: close" header so that the// server will close the socket after transmitting the response. This will// allow us to treat all data up until the EOF as the content.boost::asio::streambuf request;std::ostream request_stream(&request);request_stream << "POST " << path_  << " HTTP/1.1\r\n";request_stream << "Host: " << ip_ << "\r\n";request_stream << "Accept: */*\r\n";request_stream << "Connection: close\r\n";request_stream << "Content-Type: application/json; charset=utf-8 \r\n";request_stream << "Content-Length: " << content_.length() << "\r\n";request_stream  << "\r\n";request_stream  << content_;// Send the request.boost::function0<void> f = boost::bind(&HttpClient::wait_timeout,this, &socket); incrementAliveThread();    boost::thread t(f); boost::asio::write(socket, request);// Read the response status line. The response streambuf will automatically// grow to accommodate the entire line. The growth may be limited by passing// a maximum size to the streambuf constructor.boost::asio::streambuf response;boost::asio::read_until(socket, response, "\r\n");// Check that response is OK.std::istream response_stream(&response);std::string http_version;response_stream >> http_version;unsigned int status_code;response_stream >> status_code;std::string status_message;std::getline(response_stream, status_message);if (!response_stream || http_version.substr(0, 5) != "HTTP/"){interruptThread();LOGGER_ERROR("Invalid response" );return 1;}if (status_code != 200){interruptThread();LOGGER_ERROR("Response returned with status code " << status_code);return 2;}// Read the response headers, which are terminated by a blank line.boost::asio::read_until(socket, response, "\r\n\r\n");// Process the response headers.std::string header;while (std::getline(response_stream, header) && header != "\r"){LOGGER_DEBUG(header);}// Write whatever content we already have to output.std::ostringstream ss;if (response.size() > 0){ss << &response;body_ = ss.str();}// Read until EOF, writing data to output as we go.boost::system::error_code error;while (boost::asio::read(socket, response,boost::asio::transfer_at_least(1), error)){ss << &response;body_ += ss.str();}{boost::mutex::scoped_lock lock(mu_); cond_.notify_all();}LOGGER_DEBUG("response body: " << body_);
if (error != boost::asio::error::eof)throw boost::system::system_error(error);}catch (std::exception& e){interruptThread();LOGGER_ERROR("Exception: " << e.what());return 3;}interruptThread();LOGGER_INFO("post request succeed");return 0;}

参考:



0 0
原创粉丝点击