0
点赞
收藏
分享

微信扫一扫

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

举报

相关推荐

0 条评论