看到C++0x的lambda特性,随想到boost::asio,于是拿来练练手,的确很方便。但总有邪教的感觉。
以下代码的编译环境还是满苛刻的。
本人的编译环境为gcc 4.5.2 + boost 1.46。C++0x lambda则需要gcc 4.5以上版本
程序功能
命令:http-get 域名
功能:输出域名的首页,接收所有数据。因为是所有数据。所以有的数据会包含Chunk信息。
代码比较简单,都是最基本的应用,所以没啥注释。由于asio的handler全使用了lambda,代码整洁了许多,没有了长长的bind。
#include <string> #include <iostream> #include <algorithm> #include <boost/asio.hpp> using namespace std; using namespace boost; using boost::asio::ip::tcp; #define CHECK_ERROR_CODE(code) if (code) { cerr << code.message() << endl; return; } class HttpClient { asio::io_service &io_service_; asio::streambuf buffer_; tcp::socket socket_; tcp::resolver resolver_; string domain_; public: HttpClient(asio::io_service &io_service) : io_service_(io_service), socket_(io_service), resolver_(io_service) { } void get(const string &domain) { resolve(domain); } void resolve(const string &domain) { domain_ = domain; tcp::resolver::query query(domain, "http"); resolver_.async_resolve(query, [this](const system::error_code &code, tcp::resolver::iterator iterator) { CHECK_ERROR_CODE(code); connect( iterator->endpoint() ); } ); } void connect(tcp::endpoint remote_endpoint) { socket_.async_connect(remote_endpoint, [this](const system::error_code &code) { CHECK_ERROR_CODE(code); send_header(); } ); } void send_header() { string request_header("GET / HTTP/1.1\r\nHost: "+domain_+"\r\nConnection: close\r\n\r\n"); async_write(socket_, asio::buffer(request_header), asio::transfer_all(), [this](const system::error_code &code, size_t n) { CHECK_ERROR_CODE(code); recv_any(); } ); } void recv_any() { async_read(socket_, buffer_, asio::transfer_at_least(1), [this](const system::error_code &code, size_t n) { size_t size = asio::buffer_size(buffer_.data()); if (size>0) { const char *data = asio::buffer_cast<const char*>(buffer_.data()); cout.write(data, size); buffer_.consume(size); } CHECK_ERROR_CODE(code); recv_any(); } ); } }; int main(int argc, char *argv[]) { if (argc<2) { cerr << "http-get domain" << endl; return 1; } asio::io_service io_service; HttpClient client(io_service); client.get(argv[1]); io_service.run(); return 0; }
另存为http-get.cc,编译并运行
$ g++ -std=c++0x -lboost_system -lboost_thread http-get.cc -o http-get $ ./http-get www.baidu.com HTTP/1.1 200 OK Date: Sun, 27 Mar 2011 20:36:51 GMT Server: BWS/1.0 Content-Length: 6759 Content-Type: text/html;charset=gb2312 Cache-Control: private Expires: Sun, 27 Mar 2011 20:36:51 GMT Set-Cookie: BAIDUID=83C77B5AA4FFE997F526519A3612F959:FG=1; expires=Sun, 27-Mar-41 20:36:51 GMT; path=/; domain=.baidu.com P3P: CP=" OTI DSP COR IVA OUR IND COM " Connection: Close <!doctype html><html><head>< ... ... </html><!--6a95ba0cdf1459cc--> End of file