c++ - 为什么我的 C++ Boost ASIO HTTP 客户端返回不完整的响应?

标签 c++ http boost httpclient boost-asio

我是 C++ 的新手,我只是想使用 Boost ASIO Sync Http Client 实现一个简单的 HTTP Client;我从 Boost 的站点复制了示例,只是对其进行了修改以将响应作为字符串返回,而不是写入控制台。

我的代码正在调用电话并返回响应,但它是部分的 - 它在第 10 行后中断......我很困惑有人可以帮助我吗?

这是我的代码,如果您设置了 Boost,您应该能够复制/粘贴并运行它。

我在 Windows 7 上,使用带有 Boost 1.47 的 Visual Studio 2010。

提前致谢。

-塞尔坎

#include <iostream>
#include <istream>
#include <ostream>
#include <string>

#include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/assign/list_inserter.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>

using boost::asio::ip::tcp;

typedef boost::gregorian::date Calendar;



std::string httpClient(std::string host, std::string path){
    std::string res = "";

    try{
        boost::asio::io_service io_service;

        // Get a list of endpoints corresponding to the server name.
        tcp::resolver resolver(io_service);
        tcp::resolver::query query(host, "http");
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        tcp::resolver::iterator end;

        // Try each endpoint until we successfully establish a connection.
        tcp::socket socket(io_service);
        boost::system::error_code error = boost::asio::error::host_not_found;
        while(error && endpoint_iterator != end){
            socket.close();
            socket.connect(*endpoint_iterator++, error);
        }

        if(error){ throw boost::system::system_error(error); }

        // 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 << "GET " << path << " HTTP/1.0\r\n";
        request_stream << "Host: " << host << "\r\n";
        request_stream << "Accept: */*\r\n";
        request_stream << "Connection: close\r\n\r\n";

        // Send the request.
        boost::asio::write(socket, request);

        // Read the response status line.
        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/"){
            std::cout << "Invalid response\n";
        }
        if(status_code != 200){
            std::cout << "Response returned with status code " << status_code << "\n";
        }

        // Read the response headers, which are terminated by a blank line.
        boost::asio::read_until(socket, response, "\r\n\r\n");

        // Write whatever content we already have to output.
        if(response.size() > 0){
            std::ostringstream oss;
            oss << &response;
            res = oss.str();
        }

        // Read until EOF, writing data to output as we go.
        while(boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error)){
            //std::cout << &response; // don't want to print just return
        }

        if(error != boost::asio::error::eof){ throw boost::system::system_error(error); }

    }catch(std::exception& e){
        std::cout << "Exception: " << e.what() << "\n";
    }

    return res;
}


int main(int argc, char* argv[]){
    std::cout << httpClient("download.finance.yahoo.com", "/d/quotes.csv?s=aapl,aig,msft,jpm,WFC,BAC,C,GS,USB,AXP,MS,MET,BK,PNC,PRU,SPG,AFL,TRV,COF,STT,ACE,BBT,CME,SCHW&f=sl1d1t1");

    return 0;
}

它应该返回:

"AAPL",384.62,"11/11/2011","4:00pm" “AIG”,23.85,“2011 年 11 月 11 日”,“下午 4:01” “MSFT”,26.91,“11/11/2011”,“下午 4:00” “摩根大通”,33.28,“2011 年 11 月 11 日”,“下午 4:01” “WFC”,25.65,“11/11/2011”,“下午 4:00” “BAC”,6.21,“11/11/2011”,“下午 4:00” “C”,29.33,“11/11/2011”,“下午 4:00” “GS”,101.66,“11/11/2011”,“下午 4:00” “USB”,25.94,“11/11/2011”,“下午 4:00” “AXP”,50.37,“11/11/2011”,“下午 4:00” “MS”,16.36,“11/11/2011”,“下午 4:00” “遇见”,33.07,“11/11/2011”,“下午 4:00” “BK”,21.51,“11/11/2011”,“下午 4:00” “PNC”,53.87,“2011 年 11 月 11 日”,“下午 4:01” “PRU”,54.05,“11/11/2011”,“下午 4:01” "SPG",127.97,"11/11/2011","4:02pm" “AFL”,44.87,“11/11/2011”,“下午 4:01” “TRV”,58.43,“11/11/2011”,“下午 4:04” “COF”,45.02,“2011 年 11 月 11 日”,“下午 4:01” “STT”,41.24,“11/11/2011”,“下午 4:02” “王牌”,71.24,“11/11/2011”,“下午 4:01” “BBT”,23.58,“11/11/2011”,“下午 4:00” “CME”,263.57,“11/11/2011”,“下午 4:00” "SCHW",12.36,"11/11/2011","4:00pm"

但它返回:

日期:2011 年 11 月 12 日星期六 21:34:23 GMT P3P: policyref="http://p3p.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV” 缓存控制:私有(private) 连接:关闭 内容类型:应用程序/八位字节流

"AAPL",384.62,"11/11/2011","4:00pm" “AIG”,23.85,“2011 年 11 月 11 日”,“下午 4:01” “MSFT”,26.91,“11/11/2011”,“下午 4:00” “摩根大通”,33.28,“2011 年 11 月 11 日”,“下午 4:01” "WFC",25.65,"11/11/

最佳答案

你已经注释掉了这一行

//std::cout << &response;

现在,我知道您不希望函数打印出结果而是返回它。但是,包含该注释掉的行的循环会读出响应的其余部分,现在您只是将其丢弃。您需要将其捕获到您的返回值变量中。一个简单的解决方法是用

替换注释掉的行
std::ostringstream oss;
oss << &response;
res += oss.str();

但这不是最简洁的方法 - 您可能应该让这些东西在 response 中累积并在最后将其转换为字符串。

关于c++ - 为什么我的 C++ Boost ASIO HTTP 客户端返回不完整的响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8106566/

相关文章:

c++ - 打印特定板 C++ 的最有效代码

c++ - 通过仿函数断开 boost 信号 2 连接

web-services - 如何在 API 和各种客户端之间创建全双工通信?

javascript - 当 http 响应状态为 400 时使用 fetch api 获取自定义错误消息

node.js - 如何使用node.js在两台计算机之间共享本地文件?

c++ - std::string& 与 boost::string_ref

c++ - 如何使用模板函数作为 Boost::Unit-test 的自定义谓词

c++ - 在 boost::bind 中使用已删除的函数

c++ - 将传感器数据发布给制图师

c++ - Gradle Cpp-Application 未在 Windows 中检测到 gcc