2011-11-17 39 views
3

我是使用boost.asio的新手,但我想設計一個簡單的例程來從URL獲取數據並將其保存到內存緩衝區。根據一個例子,我發現,我想出了以下內容:Boost.asio socket - 爲什麼沒有可用的字節

//data_url.hpp 

#include <boost/asio.hpp> 
#include <string> 
#include <vector> 

struct data { 
    data(); 
    boost::asio::io_service io_service; 
    boost::asio::ip::tcp::resolver resolver; 
    boost::asio::ip::tcp::socket socket; 
    std::vector<char> buffer; 
    std::string host; 
    std::string path; 
    std::string port; 
}; 

void setup_url(std::string hst, 
       std::string pth, 
       std::string prt = "80"); 

std::vector<char> & get_data_from_url(); 

void resolve_handler(const boost::system::error_code & ec, 
        boost::asio::ip::tcp::resolver::iterator it); 

void connect_handler(const boost::system::error_code & ec); 

void read_handler(const boost::system::error_code & ec, 
        std::size_t bytes_transferred); 

實施

//data_url.cpp 

#include <data_url.hpp> 
#include <iostream> 

data::data() : io_service(), resolver(io_service), socket(io_service) 
      , buffer(), host(), path(), port() {} 
data d; 

void setup_url(std::string hst, std::string pth, std::string prt) { 
    d.host = hst; 
    d.path = pth; 
    d.port = prt; 
} 

std::vector<char> & get_data_from_url() { 
    boost::asio::ip::tcp::resolver::query query(d.host, d.port); 
    d.resolver.async_resolve(query, resolve_handler); 
    d.io_service.run(); 
    return d.buffer; 
} 

void resolve_handler(const boost::system::error_code & ec, 
        boost::asio::ip::tcp::resolver::iterator it) { 
    if(!ec) { 
    d.socket.async_connect(*it, connect_handler); 
    } 
} 

void connect_handler(const boost::system::error_code & ec) { 
    if(!ec) { 
    boost::asio::write(d.socket, 
         boost::asio::buffer(std::string("GET ") + 
              std::string(d.path) + 
              std::string(" HTTP 1.1\r\n") + 
              std::string("Host: ") + 
              std::string(d.host) + 
              std::string("\r\n\r\n"))); 
    boost::system::error_code ec_avail; 
    d.buffer.resize(d.socket.available(ec_avail)); 
    d.socket.async_read_some(boost::asio::buffer(d.buffer), 
          read_handler); 
    } 
} 

void read_handler(const boost::system::error_code & ec, 
        std::size_t bytes_transferred) { 
    if(!ec) { 
    d.socket.async_read_some(boost::asio::buffer(d.buffer), 
          read_handler); 
    } 
} 

然後,我

#include <data_url.hpp> 

int main(int argc, char *argv[]) { 
    setup_url("www.boost.org", "/"); 
    std::vector<char> data; 
    data = get_data_from_url(); 

    return 0; 
} 

該代碼調用read_handler不休,並永遠不會終止運行。我用不同的頁面嘗試過,並沒有什麼區別。

此外,在content_handler函數中,我使用socket.available()調整矢量大小。這是爲了使代碼儘可能通用,以便我可以閱讀任何頁面而不必知道它的大小。但是,當我撥打socket.available()時,它將返回零並將ec_avail中的錯誤代碼設置爲「未定義的錯誤」。

正如我所提到的,我是使用boost.asio的新手,顯然我在這裏錯過了一些東西。我很感謝幫助解決這些錯誤和任何其他建議/建議。

回答

3

您的插座是不可能調用write後,立即有可用的數據,所以你調整大小的方法可能是行不通的,然後你調用async_read_some大小爲0

async_read_some整點的緩衝在異步操作完成之前它不需要填充整個緩衝區,所以使用基本塊大小類似8192的臨時緩衝區,並且在每次成功調用讀取處理程序之後,將讀取的數據追加到你的主緩衝區。

ASIO不是一個HTTP庫,所以如果你使用它來通過HTTP下載文件,你需要做大量的數據處理來解析頭文件並確定響應類型它是,確定內容的長度和編碼等。

如果你只是想使用它的HTTP的東西,我會強烈推薦使用Poco,因爲它有內置的HTTP流支持。

+0

這是很棒的信息。非常感謝。我會看看波科。 –

相關問題