boost::asio 与 C++0x

看到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

附:http-get源码打包下载

共1条Pingback

发表评论

电子邮件地址不会被公开。 必填项已用*标注