您的位置:首页 > 理论基础 > 计算机网络

开始搞实验的杂谈(二)-------主要关于http_async_client

2013-11-20 10:55 330 查看
第一:在慢慢学boost的asio库,发现用io_service的时候,argv【1】一般就是默认是localhost啦,当然分布式的时候就是ip了,额,端口号不能用8080,记住。

第二:那个blocking_tcp_echo_client对于async_tcp_echo_server也是可以用的,没有区别

第三:说说从async_http_client中总结的一些东西,很杂乱噢:

首先这个client是异步的,我在每一个函数里面都设了断点之后,貌似发现io_service。run到底是怎么运作了,下面

boost::asio::io_service io_service;
client temp_client(io_service, argv[1], argv[2]);
io_service.run();


client(boost::asio::io_service& io_service,
const string& server, const string& path):resolver_(io_service), socket_(io_service)
{
// 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.
std::ostream request_stream(&request_);
request_stream << "GET " << path << " HTTP/1.0\r\n";
request_stream << "Host: " << server << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";

//Start an asynchronous resolve to translate the server and service names
//into a list of endpoints
tcp::resolver::query query(server, "http");
resolver_.async_resolve(query,
boost::bind(&client::handle_resolve, this,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator));

}


代码当中的,程序的流程是,先调用了client的构造函数,然后搞定之后跳出来回到main,run执行了之后,才行到handle_resolve这个函数里面,ok,然后就是一个接一个地往下执行了,这个源代码还不错的,现实当中可能不需这样写的,但是它把每一步都分开装在不同的函数里面,对我这种菜鸟初学者来说还是很容易看懂的。

第四:ostream和istream,额好吧,我承认我以前没用过,两个的构造函数都是 iostream(string*),比如 ostream(&request_),把request这个字符串引用(或说是首地址给那个流),然后以后ostream每每执行 << 的时候,就会把相同的内容赋给request了,类似地,istream也是这样的,如:一个 >> 是以空格分隔符的,所以那两行 >> 就分别把http的version 和状态码给了两个变量了,然后getline就当然是一行为单位的了,以行结束符为分隔。

istream response_stream(&response_);
string http_version;
unsigned int status_code;
string status_message;

response_stream >> http_version;
response_stream >> status_code;

getline(response_stream, status_message);


像对socket的操作也是一样的,write就是从request写到socket里面去,read就是从socket读出来然后写到response里面去。

然后其实在读例子当中的boost的一个license的时候,因为用来装内容的buffer默认只分配了512个字节,所以其实是要分几次才能读完的,特意查了下官网关于async_read的用法,如下:

completion_condition
The function object to be called to determine whether the read operation is complete. The signature of the function object must be:
std::size_t completion_condition(
// Result of latest async_read_some operation.
const boost::system::error_code& error,

// Number of bytes transferred so far.
std::size_t bytes_transferred
);
A return value of 0 indicates that the read operation is complete. A non-zero return value indicates the maximum number of bytes to be read on the next call to the stream's async_read_some function.


This function is used to asynchronously read a certain number of bytes of data from a stream. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true:

The supplied buffer is full (that is, it has reached maximum size).
The completion_condition function object returns 0.


比如说那个transfer_at_least(1),其实就是要等到它返回零的时候,这个操作才会停止,否则会再次handle_read_content,因为返回零就标示刚才连一个字节都没有传输了,还有另外一个条件也可以促使这个读的操作继续进行,那就是如果用来写进读的那个buffer是满的,那么就继续读呗~~~~

所以我在几个handle_read的函数下面加了些输出,来看看各执行了多少次,输出表明status line 和 header都是一次,然后反正终于搞明白整个流程,还有一些细碎的用法是怎样的了,有几个值得注意的地方:第一个是socket,它其实被读了之后,应该理解成,它的内容是一次性的,每次读取它都会被抽出来一样,所以经过了几个函数这样往下传递的读取,下一个函数只会从上一个函数读完之后的残渣开始的地方继续读,所以在content的时候一次是读不完的,当一次不完之后会继续用bind来指定继续要执行的handler还是那个handle_read-content

而这部分的代码只是表示将header和余下的内容部分分开来输出而已,没有多大的意义,其实所以的内容都可以直接用handle_read_content的那个函数来不断地地callback然后输出完所有的信息,这里有一点要注意的是,因为istream response-stream(&response_)这个初始化等于已经将一块缓冲区交给两个同步的但只是名字不同的指针来管理了,所以在进行完while循环的那个getline之后,下面那个if语输出的就是header之后余下的那些content的内容了。

while (getline(response_stream, header) && header != "\r")
{
cout << header << endl;
}
cout << "\n";

if (response_.size() > 0)
{
cout << &response_;
}


OK,这个就学到这里了,哎,这也花了两天时间了,希望把每个细节都搞通会对之后的多线程请求部分会有些帮助吧,搞啊!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: