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

Why my C++ Boost ASIO HTTP Client Returning Incomplete Response?

本文关键字:响应 返回 客户端 c++ 我的 Boost ASIO HTTP 为什么      更新时间:2023-10-16

我是c++的新手,我只是想实现一个简单的HTTP客户端使用Boost ASIO同步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.0rn";
        request_stream << "Host: " << host << "rn";
        request_stream << "Accept: */*rn";
        request_stream << "Connection: closernrn";
        // Send the request.
        boost::asio::write(socket, request);
        // Read the response status line.
        boost::asio::streambuf response;
        boost::asio::read_until(socket, response, "rn");
        // 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 responsen";
        }
        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, "rnrn");
        // 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;
}

它应该返回:

" apple ", 384.62,"11/11/2011","下午1:00"美国国际集团",23.85,"11/11/2011"、"4:01pm"微软",26.91,"11/11/2011","下午1:00"大摩",33.28,"11/11/2011"、"4:01pm"wells",25.65,"11/11/2011","下午1:00" BAC ", 6.21,"11/11/2011","下午1:00"C",29.33,"11/11/2011","下午1:00"GS",101.66,"11/11/2011","下午1:00"USB",25.94,"11/11/2011","下午1:00"AXP",50.37,"11/11/2011","下午1:00"女士",16.36,"11/11/2011","下午1:00"遇见",33.07,"11/11/2011","下午1:00"汉堡王",21.51,"11/11/2011","下午1:00" PNC ", 53.87,"11/11/2011"、"4:01pm"保诚",54.05,"11/11/2011"、"4:01pm"厂家",127.97,"11/11/2011"、"4:02pm"澳式足球联盟",44.87,"11/11/2011"、"4:01pm"answers",58.43,"11/11/2011"、"4:04pm"咖啡",45.02,"11/11/2011"、"4:01pm"STT",41.24,"11/11/2011"、"4:02pm"王牌",71.24,"11/11/2011"、"4:01pm"《",23.58,"11/11/2011","下午1:00"芝加哥商品交易所",263.57,"11/11/2011","下午1:00"等",12.36,"11/11/2011","下午1:00"

但是它返回:

日期:2011年11月12日星期六21:34:23 GMTP3P: policyref="http://p3p.yahoo.com/w3c/p3p.xml", CP="CAO DSP or CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi public and PHY only UNI PUR fincom NAV INT DEM CNT STA POL HEA PRE GOV"cache - control:私人连接:关闭内容类型:应用程序/八进制

" apple ", 384.62,"11/11/2011","下午1:00"美国国际集团",23.85,"11/11/2011"、"4:01pm"微软",26.91,"11/11/2011","下午1:00"大摩",33.28,"11/11/2011"、"4:01pm"wells",25.65,"11/11/

你已经注释掉了这行

//std::cout << &response;

现在,我明白了你不想让函数输出结果,而是返回结果。但是,包含被注释掉的行的循环将读出响应的其余部分,现在您只需将其丢弃。您需要将其捕获到返回值变量中。一个简单的修复方法是用

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

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