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

时间:2011-11-12 18:26:38

标签: c++ http boost httpclient boost-asio

我是C ++的新手,我只是尝试使用Boost ASIO Sync Http Client实现一个简单的HTTP客户端;我从Boost的网站复制了这个例子,只是修改它以将响应作为字符串返回而不是写入控制台。

我的代码正在拨打电话,它正在返回一个响应,但它是部分的 - 它会在第10行之后切断...我很困惑有人可以帮助我吗?

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

我在Windows 7上使用Visual Studio 2010和Boost 1.47。

提前致谢。

-serkan

#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:00” “AIG”,23.85 “11/11/2011”, “下午4:01” “MSFT”,26.91 “11/11/2011”, “4:00” “JPM”,33.28 “11/11/2011”, “下午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” “MET”,33.07 “11/11/2011”, “4:00” “BK”,21.51 “11/11/2011”, “4:00” “PNC”,53.87 “11/11/2011”, “下午4:01” “PRU”,54.05 “11/11/2011”, “下午4:01” “SPG” 127.97, “11/11/2011”, “下午4点02分” “AFL”,44.87 “11/11/2011”, “下午4:01” “TRV”,58.43 “11/11/2011”, “16:04” “COF”,45.02 “11/11/2011”, “下午4:01” “STT”,41.24 “11/11/2011”, “下午4点02分” “ACE”,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:00”

但它返回:

日期: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我们的DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV“ 缓存控制:私有 连接:关闭 Content-Type:application / octet-stream

“AAPL”,384.62 “11/11/2011”, “下午4:00” “AIG”,23.85 “11/11/2011”, “下午4:01” “MSFT”,26.91 “11/11/2011”, “4:00” “JPM”,33.28 “11/11/2011”, “下午4:01” “WFC”,25.65,“11/11 /

1 个答案:

答案 0 :(得分:0)

您已注释掉

//std::cout << &response;

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

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

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