Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <istream>
- #include <ostream>
- #include <string>
- #include <boost/asio.hpp>
- #include <boost/bind/bind.hpp>
- #define BOOST_THREAD_PROVIDES_FUTURE
- #define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
- #define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
- #include <boost/thread.hpp>
- using boost::asio::ip::tcp;
- class client
- {
- public:
- client(boost::asio::io_service& io_service,
- const std::string& server, const std::string& path)
- : resolver_(io_service),
- socket_(io_service), url(server)
- {
- // 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.
- std::ostream request_stream(&request_);
- request_stream << "GET " << path << " HTTP/1.0\r\n";
- request_stream << "Host: " << server << "\r\n";
- request_stream << "Accept: */*\r\n";
- request_stream << "Connection: close\r\n\r\n";
- // Start an asynchronous resolve to translate the server and service names
- // into a list of endpoints.
- resolver_.async_resolve(server, "6969",
- boost::bind(&client::handle_resolve, this,
- boost::asio::placeholders::error,
- boost::asio::placeholders::results));
- }
- boost::future<std::string> GetResponse() {
- return promise_resp.get_future();
- }
- private:
- void handle_resolve(const boost::system::error_code& err,
- const tcp::resolver::results_type& endpoints)
- {
- if (!err)
- {
- // Attempt a connection to each endpoint in the list until we
- // successfully establish a connection.
- boost::asio::async_connect(socket_, endpoints,
- boost::bind(&client::handle_connect, this,
- boost::asio::placeholders::error));
- }
- else
- {
- SetException("Error resolve: " + err.message() + "\n");
- }
- }
- void handle_connect(const boost::system::error_code& err)
- {
- if (!err)
- {
- // The connection was successful. Send the request.
- boost::asio::async_write(socket_, request_,
- boost::bind(&client::handle_write_request, this,
- boost::asio::placeholders::error));
- }
- else
- {
- SetException("Error connect: " + err.message() + "\n");
- }
- }
- void handle_write_request(const boost::system::error_code& err)
- {
- if (!err)
- {
- // 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::async_read_until(socket_, response_, "\r\n",
- boost::bind(&client::handle_read_status_line, this,
- boost::asio::placeholders::error));
- }
- else
- {
- SetException("Error request: " + err.message() + "\n");
- }
- }
- void handle_read_status_line(const boost::system::error_code& err)
- {
- if (!err)
- {
- // 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/")
- {
- SetException("Invalid response\n");
- return;
- }
- if (status_code != 200)
- {
- SetException("Response returned with status code " + std::to_string(status_code) + "\n");
- return;
- }
- // Read the response headers, which are terminated by a blank line.
- boost::asio::async_read_until(socket_, response_, "\r\n\r\n",
- boost::bind(&client::handle_read_headers, this,
- boost::asio::placeholders::error));
- }
- else
- {
- SetException("Error status line: " + err.message() + "\n");
- }
- }
- void handle_read_headers(const boost::system::error_code& err)
- {
- if (!err)
- {
- // Start reading remaining data until EOF.
- boost::asio::async_read(socket_, response_,
- boost::asio::transfer_at_least(1),
- boost::bind(&client::handle_read_content, this,
- boost::asio::placeholders::error));
- }
- else
- {
- SetException("Error head: " + err.message() +"\n");
- }
- }
- void handle_read_content(const boost::system::error_code& err)
- {
- if (!err)
- {
- // Continue reading remaining data until EOF.
- boost::asio::async_read(socket_, response_,
- boost::asio::transfer_at_least(1),
- boost::bind(&client::handle_read_content, this,
- boost::asio::placeholders::error));
- }
- else if (err == boost::asio::error::eof) {
- SetResponse();
- }
- else
- {
- SetException("Error content: " + err.message() + "\n");
- }
- }
- void SetResponse() {
- std::istream response_stream(&response_);
- std::string response_str {std::istreambuf_iterator<char>(response_stream),
- std::istreambuf_iterator<char>()};
- promise_resp.set_value(response_str);
- }
- void SetException(std::string const & excp){
- std::logic_error le (excp);
- promise_resp.set_exception(std::move(le));
- }
- tcp::resolver resolver_;
- tcp::socket socket_;
- boost::asio::streambuf request_;
- boost::asio::streambuf response_;
- boost::promise<std::string> promise_resp;
- std::string url;
- };
- int main()
- {
- SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
- try
- {
- boost::asio::io_service io_service;
- std::stringstream input {
- "pubt.net\n"
- "210.244.71.25\n"
- "tracker.dler.org\n"
- "125.227.35.196\n"
- "retracker.local\n"
- "tracker2.wasabii.com.tw\n"
- "tracker.filetracker.pl\n"
- "46.4.109.148\n"
- "87.248.186.252\n"
- "tracker.grepler.com\n"
- "tracker.tiny-vps.com"
- };
- std::string request_str = "/announce?info_hash=%AFWo%87r%DA%82%B7%F5%8B%B6%21%1C%2AF%3B%F8%7BV%20";
- std::vector<std::shared_ptr<client>> urls;
- std::string line;
- while (std::getline(input, line)) {
- urls.push_back(std::make_shared<client>(io_service, line, request_str));
- }
- std::vector<boost::future<std::string>> results;
- for (auto &el: urls) {
- results.push_back(el->GetResponse());
- }
- std::thread t([&] { SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); io_service.run();});
- boost::promise<std::string> any_res;
- struct DoneCheck {
- private:
- boost::promise<std::string> & result;
- boost::asio::io_service & service;
- public:
- DoneCheck(boost::promise<std::string> & r, boost::asio::io_service & serv) : result(r), service(serv) {};
- void operator()(boost::future<std::vector<boost::future<std::string>>> result_args) {
- auto results = result_args.get();
- auto any_res = results.begin();
- try {
- result.set_value(any_res->get()); // << тут надолго останавливается работа
- service.dispatch([&]{service.stop(); service.reset();});
- } catch (std::exception & excep) {
- results.erase(results.begin(), results.begin() + 1);
- if (!results.empty())
- boost::when_any(results.begin(), results.end())
- .then(std::move(*this));
- else { result.set_exception(excep); }
- }
- }
- };
- boost::when_any(results.begin(), results.end())
- .then(DoneCheck{any_res, io_service});
- try {
- std::cout << any_res.get_future().get() << std::endl;
- } catch (std::exception &excp) {
- std::cerr << excp.what() << std::endl;
- }
- t.join();
- }
- catch (std::exception& e)
- {
- std::cout << "Exception: " << e.what() << "\n";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement