当前位置:编程学习 > 网站相关 >>

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);


 

 

补充:综合编程 , 其他综合 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,