Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何修复Boost::Asio客户端Http请求错误? 我试图精益::ASIO网络库,用于C++,但我坚持使用异步线程进行请求。_C++_Multithreading_Boost_Boost Asio - Fatal编程技术网

如何修复Boost::Asio客户端Http请求错误? 我试图精益::ASIO网络库,用于C++,但我坚持使用异步线程进行请求。

如何修复Boost::Asio客户端Http请求错误? 我试图精益::ASIO网络库,用于C++,但我坚持使用异步线程进行请求。,c++,multithreading,boost,boost-asio,C++,Multithreading,Boost,Boost Asio,守则: #include "stdafx.h" #include <iostream> #include <boost/asio.hpp> #include <boost/asio/ts/buffer.hpp> #include <boost/asio/ts/internet.hpp> #include <boost/system/error_code.hpp> std::vector<char> vB

守则:

#include "stdafx.h"
#include <iostream>
#include <boost/asio.hpp>
#include <boost/asio/ts/buffer.hpp>
#include <boost/asio/ts/internet.hpp>
#include <boost/system/error_code.hpp>

std::vector<char> vBuffrer(20 * 1024);

void GrabSomeData(boost::asio::ip::tcp::socket& socket) {

    socket.async_read_some(boost::asio::buffer(vBuffrer.data(), vBuffrer.size()),
        [&](std::error_code ec, std::size_t length)
        //boost::system::error_code ec
    {
        if (!ec)
        {
            std::cout << "\n\nRead" << length << "bytes\n\n";

            for (int i = 0; i < length; i++)
                std::cout << vBuffrer[i];
            GrabSomeData(socket);
        }
    });


}

int main()
{
    boost::system::error_code ec;
    boost::asio::io_context context;
    boost::asio::io_context::work idleWork(context);
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::make_address("13.107.21.200",ec),80);
    boost::asio::ip::tcp::socket socket(context);
    std::thread thrContext = std::thread([&]() {context.run(); });
    std::cout << "Starting " << std::endl;
    socket.connect(endpoint,ec);

    if (!ec)
    {
        std::cout << "Connected ! " << std::endl;
    }
    else {
        std::cout << "Fail to connect ! " << ec.message() << std::endl;

    }

    if (socket.is_open()) {

        GrabSomeData(socket);
        std::string sRequest =
            "GET /index.html HTTP/1.1\r\n"
            "Host: www.example.com\r\n"
            "Connection: close\r\n\r\n";
        socket.write_some(boost::asio::buffer(sRequest.data(), sRequest.size()), ec);

        using namespace std::chrono_literals;
        std::this_thread::sleep_for(2800ms);
        //std::this_thread::sleep_for(1ms);

        context.stop();
        if (thrContext.joinable()) thrContext.join();
    }

    system("pause");

    return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
#包括
标准:向量vBuffrer(20*1024);
void GrabSomeData(boost::asio::ip::tcp::socket和socket){
socket.async_read_some(boost::asio::buffer(vBuffrer.data(),vBuffrer.size()),
[&](标准::错误代码ec,标准::大小\u t长度)
//boost::system::错误代码ec
{
如果(!ec)
{

std::cout与评论者一样,我无法重新编写您的消息:它只是编译

  • MSVC 19,/std:c++14,Boost 1.75.0:
现在,我想看看其他问题:

  • write\u一些
    可能不会写入所有数据-您需要确保一个组合写入操作

  • 竞争条件:由于您正在线程上执行
    GrabSomeData
    ,因此 需要同步对
    tcp::socket
    缓冲区的访问
    共享资源)

    io_上下文
    本身是线程安全的

    在这种情况下,很容易避免,因为您不需要这样做 在发送请求之前,请启动异步操作:

    write(socket, boost::asio::buffer(sRequest));
    GrabSomeData(socket);
    
  • async\u read\u有些
    与写入端有类似的问题。您需要一个组合读取操作,读取预期的输出,以便
    read\u直到(socket,buf,“\r\n\r\n”)
    然后根据
    内容长度
    头、
    连接:Close
    和其他内容读取预期的内容量(想想分块编码)

    您目前没有很好的方法来存储和访问响应。使用streambuf(单一组合读取)会容易得多

    如果您想要真正可靠,请使用Beast接收HTTP/1.1响应(甚至可以分块),而不必担心响应何时完成(库会为您完成):

    auto-GrabSomeData(tcp::socket和socket){
    http::res响应;
    自动buf=boost::asio::动态缓冲区(vBuffer);
    http::read(套接字、buf、res);
    返回res;
    }
    
    哦,不要在线程上执行此操作(无论如何,这是为什么?它实际上只是引入了未定义的行为,没有任何好处):

  • 简化代码

    #include <boost/asio.hpp>
    #include <boost/beast/http.hpp>
    #include <iostream>
    #include <iomanip>
    using boost::asio::ip::tcp;
    
    std::vector<char> vBuffer; // TODO FIXME global variable
    
    auto GrabSomeData(tcp::socket& socket) {
        namespace http = boost::beast::http;
    
        http::response<http::string_body> res;
    
        auto buf = boost::asio::dynamic_buffer(vBuffer);
        http::read(socket, buf, res);
    
        return res;
    }
    
    int main() try {
        boost::asio::io_context context;
    
        std::cout << "Starting " << std::endl;
        tcp::endpoint endpoint(boost::asio::ip::make_address("13.107.21.200"), 80);
        tcp::socket   socket(context);
        socket.connect(endpoint);
    
        std::cout << "Connected" << std::endl;
    
        std::string const sRequest = "GET /index.html HTTP/1.1\r\n"
            "Host: www.example.com\r\n"
            "Connection: close\r\n"
            "\r\n";
    
        write(socket, boost::asio::buffer(sRequest));
    
        auto response = GrabSomeData(socket);
    
        std::cout << "Response body length: " << response.body().size() << std::endl;
        std::cout << "Response headers: " << response.base() << std::endl;
        std::cout << "Response body: " << std::quoted(response.body()) << std::endl;
    
        context.run(); // run_for(10s) e.g.
    } catch (boost::system::system_error const& se) {
        std::cerr << "Error: " << se.code().message() << std::endl;
    }
    

    #include <boost/asio.hpp>
    #include <boost/beast/http.hpp>
    #include <iostream>
    #include <iomanip>
    using boost::asio::ip::tcp;
    
    std::vector<char> vBuffer; // TODO FIXME global variable
    
    auto GrabSomeData(tcp::socket& socket) {
        namespace http = boost::beast::http;
    
        http::response<http::string_body> res;
    
        auto buf = boost::asio::dynamic_buffer(vBuffer);
        http::read(socket, buf, res);
    
        return res;
    }
    
    int main() try {
        boost::asio::io_context context;
    
        std::cout << "Starting " << std::endl;
        tcp::endpoint endpoint(boost::asio::ip::make_address("13.107.21.200"), 80);
        tcp::socket   socket(context);
        socket.connect(endpoint);
    
        std::cout << "Connected" << std::endl;
    
        std::string const sRequest = "GET /index.html HTTP/1.1\r\n"
            "Host: www.example.com\r\n"
            "Connection: close\r\n"
            "\r\n";
    
        write(socket, boost::asio::buffer(sRequest));
    
        auto response = GrabSomeData(socket);
    
        std::cout << "Response body length: " << response.body().size() << std::endl;
        std::cout << "Response headers: " << response.base() << std::endl;
        std::cout << "Response body: " << std::quoted(response.body()) << std::endl;
    
        context.run(); // run_for(10s) e.g.
    } catch (boost::system::system_error const& se) {
        std::cerr << "Error: " << se.code().message() << std::endl;
    }
    
    #包括
    #包括
    #包括
    #包括
    使用boost::asio::ip::tcp;
    std::vector vBuffer;//TODO FIXME全局变量
    自动抓取SomeData(tcp::socket和socket){
    命名空间http=boost::beast::http;
    http::res响应;
    自动buf=boost::asio::动态缓冲区(vBuffer);
    http::read(套接字、buf、res);
    返回res;
    }
    int main()尝试{
    boost::asio::io_上下文;
    
    std::cout感谢@sehe的回答和建议,花了这么长时间,但我已经升级到新的Windows10VisualStudio2019,以及Boost 1_76,问题解决了


    这些错误与代码完全无关!

    不编译“致命错误:stdafx.h:没有这样的文件或目录”你是在Linux上编译的吗?是的;请使用标准的headersIt它是Windows的标准,stdafx.h是Windows的东西。如果我从Header中删除它,它就不会在Visual Studio上编译。这并不是说我喜欢它在Windows上,但教程是这样的,而且它应该是跨平台的!仅供参考,这里编译/链接/运行良好(显然,没有stdafx.h)
    #include <boost/asio.hpp>
    #include <boost/beast/http.hpp>
    #include <iostream>
    #include <iomanip>
    using boost::asio::ip::tcp;
    
    std::vector<char> vBuffer; // TODO FIXME global variable
    
    auto GrabSomeData(tcp::socket& socket) {
        namespace http = boost::beast::http;
    
        http::response<http::string_body> res;
    
        auto buf = boost::asio::dynamic_buffer(vBuffer);
        http::read(socket, buf, res);
    
        return res;
    }
    
    int main() try {
        boost::asio::io_context context;
    
        std::cout << "Starting " << std::endl;
        tcp::endpoint endpoint(boost::asio::ip::make_address("13.107.21.200"), 80);
        tcp::socket   socket(context);
        socket.connect(endpoint);
    
        std::cout << "Connected" << std::endl;
    
        std::string const sRequest = "GET /index.html HTTP/1.1\r\n"
            "Host: www.example.com\r\n"
            "Connection: close\r\n"
            "\r\n";
    
        write(socket, boost::asio::buffer(sRequest));
    
        auto response = GrabSomeData(socket);
    
        std::cout << "Response body length: " << response.body().size() << std::endl;
        std::cout << "Response headers: " << response.base() << std::endl;
        std::cout << "Response body: " << std::quoted(response.body()) << std::endl;
    
        context.run(); // run_for(10s) e.g.
    } catch (boost::system::system_error const& se) {
        std::cerr << "Error: " << se.code().message() << std::endl;
    }
    
    Starting 
    Connected
    Response body length: 194
    Response headers: HTTP/1.1 400 Bad Request
    Transfer-Encoding: chunked
    X-MSEdge-Ref: 0BstXYAAAAACeQ2y+botzQISiBe2U3iGCQ0hHRURHRTE0MDgARWRnZQ==
    Date: Sun, 21 Mar 2021 22:39:02 GMT
    Connection: close
    
    Response body: "<h2>Our services aren't available right now</h2><p>We're working to restore all services as soon as possible. Please check back soon.</p>0BstXYAAAAACeQ2y+botzQISiBe2U3iGCQ0hHRURHRTE0MDgARWRnZQ=="