Boost::asio范例分析 客户端
为了方便描述,这里只分析一下同步实现,异步实现方式和同步方式的流程是一致的,只是在函数调用的方式上有些区别.分析清楚了同步方式,在看异步实现,也很容易.
这个HTTP范例实现了客户端向服务端请求文件内容的功能,客户端给出一个文件名称,服务端在本地寻找文件,并将文件内容(文本文件)返回给客户端.
main函数首先检查传递给exe执行文件的参数,第一个参数是服务端的IP地址,第二个参数是请求的文件名称,如果仅指定了目录而没有具体的文件名,则在这个目录中查找index.htm文件.
//定义io_service对象实例,任何使用asio的程序中都要进行定义,是asio库的核心实现.
boost::asio::io_service io_service;
//argv[1]是服务端IP地址,由程序调用方提供,
//在指定服务器上寻找http服务,并获取网络端点
tcp::resolver resolver(io_service);
tcp::resolver::query query(argv[1], "http");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
// 尝试获取到的每个端点,直到建立了一个有效的链接.
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
至此,链接建立成功.接下来就是向服务端发送和接受数据了.
//建立一个流缓冲区,用来存储发送和接受的数据
boost::asio::streambuf request;
//将流缓冲区与一个输出流ostream绑定,对ostream的输出操作最终都存入到流缓冲区.
std::ostream request_stream(&request);
//根据客户端与服务端制定的协议,组织HTTP请求包的头信息.argv[2]指定了文件名称.
request_stream << "GET " << argv[2] << " HTTP/1.0\r\n";
request_stream << "Host: " << argv[1] << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
//向服务端发送HTTP请求
boost::asio::write(socket, request);
这时HTTP服务端接受到客户端发送的请求后,按双边协议对请求信息进行解析,获取到文件名称和HTTP协议的版本号,并进行相应的处理,将HTTP响应状态信息,包头信息和文件内容发送给客户端.客户端接收这些信息,并进行检查处理.
接收响应的状态信息:
//定义接收响应数据的流缓冲区
boost::asio::streambuf response;
//从服务端接收响应包的头信息,描述响应的状态
//流缓冲区可根据接收的数据自动调节大小,可在其构造函数中指定最大流缓冲区.
boost::asio::read_until(socket, response, "\r\n");
检查响应包的状态:
//将流缓冲区与istream相关联,可方便的从流缓冲区中提取出信息
std::istream response_stream(&response);
std::string http_version;
//获取http版本号
response_stream >> http_version;
unsigned int status_code;
//获取响应信息的状态码
response_stream >> status_code;
std::string status_message;
//获取状态信息
std::getline(response_stream, status_message);
//检查包是否为HTTP请求的响应包
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
std::cout << "Invalid response\n";
return 1;
}
if (status_code != 200)//状态码为200表示请求成功,否则失败
{
std::cout << "Response returned with status code " << status_code << "\n";
return 1;
}
如果检查通过,则开始接收响应包的包头.
boost::asio::read_until(socket, response, "\r\n\r\n");
//处理响应包头信息
std::string header;
while (std::getline(response_stream, header) && header != "\r")
std::cout << header << "\n";
std::cout << "\n";
// 打印出所有输出的信息
if (response.size() > 0) std::cout << &response;
现在开始接收文件内容,直到遇到了EOF符号,并将接收到的数据直接输出
boost::system::error_code error;
//read函数返回接收到的字节数,这里用了while循环,表示一直接收,直到接收不到为止.
// transfer_at_least 函数返回transfer_at_least_t类型,
//这是一个函数对象,会将接收到的数据字节数与其参数相比较,
//如果大于等于指定数量则返回,这里指定为1表示接收到数据就返回处理.
while (boost::asio::read(socket, response,
boost::asio::transfer_at_least(1), error))
std::cout << &response;//直接将接收到的数据进行显示
if (error != boost::asio::error::eof)
throw boost::system::system_error(error);
补充:综合编程 , 其他综合 ,