Boost.Asio-使用Boost.Asio和OpenWeatherMap API获取天气的程序源码(同步读取、异步读取)

OpenWeatherMap API是一个提供天气数据的开放接口,可以通过该接口获取全球范围内的实时天气。
1.获取OpenWeatherMap API的密钥
去官网https://openweathermap.org注册后,自主生成密钥,如图

在这里插入图片描述

2.获取用的代码(方法1,同步读取,写法通用 测试环境下推荐这种)

#include "stdafx.h"
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <algorithm>

using boost::asio::ip::tcp;
int main()
{
	try
	{
		boost::asio::io_context io_context;

		// 创建一个TCP连接
		tcp::resolver resolver(io_context);
		tcp::resolver::results_type endpoints = resolver.resolve("api.openweathermap.org", "http");

		tcp::socket socket(io_context);
		boost::asio::connect(socket, endpoints);

		// 发送HTTP请求
		std::string request = "GET /data/2.5/weather?id=1816670&appid=c7c9b4。。密钥需换成自己的 HTTP/1.1\r\n"
			"Host: api.openweathermap.org\r\n"
			"Connection: close\r\n\r\n";
		boost::asio::write(socket, boost::asio::buffer(request));

		// 读取服务器响应
		boost::asio::streambuf response;
		boost::asio::read_until(socket, response, "\r\n");

		// 输出响应结果
		std::istream response_stream(&response);
		std::string http_version;
		response_stream >> http_version;
		unsigned int status_code;
		response_stream >> status_code;

		if (status_code == 200)
		{
			std::string status_message;
			std::getline(response_stream, status_message);
			std::cout << "HTTP/1.1 " << status_code << " " << status_message << std::endl;

			// 读取并输出天气数据
			std::cout << &response << std::endl;
		}
		else
		{
			std::cout << "HTTP request failed with status code: " << status_code << std::endl;
		}
	}
	catch (std::exception& e)
	{
		std::cout << "Exception: " << e.what() << std::endl;
	}

	return 0;
}

2.获取用的代码(方法2,同步读取,简单容易理解)

int main(int argc,char* argv[])
{
	try
	{
		//if (argc != 2)
		//{
		//	std::cerr << "Usage: daytime_client <host>" << std::endl;
		//	return 1;
		//}

		tcp::iostream s("api.openweathermap.org", "http");
		if (!s)
		{
			std::cout << "Unable to connect: " << s.error().message() << std::endl;
			return 1;
		}
		s << "GET /data/2.5/weather?q=BeiJing&appid=c7c9b.。。你的密钥 HTTP/1.1\r\n";
		s << "Host: api.openweathermap.org\r\n";
		s << "Connection: close\r\n\r\n";

		// Check that response is OK.
		std::string http_version;
		s >> http_version;
		unsigned int status_code;
		s >> status_code;
		std::string status_message;
		std::getline(s, status_message);
		if (!s || http_version.substr(0, 5) != "HTTP/")
		{
			std::cout << "Invalid response\n";
			return 1;
		}
		if (status_code != 200)
		{
			std::cout << "Response returned with status code " << status_code << "\n";
			return 1;
		}

		std::cout << http_version << " " << status_code << " " << status_message << std::endl;
		// Process the response headers, which are terminated by a blank line.
		std::string header;
		while (std::getline(s, header) && header != "\r")
		{	std::cout << header << "\n";}
		std::cout << "\n";

		// Write the remaining data to output.
		std::cout << s.rdbuf();
	}
	catch (std::exception& e)
	{
		std::cout << "Exception: " << e.what() << std::endl;
	}

	return 0;
}

2.获取用的代码(方法3, 异步读取,真实生产环境下推荐)

const std::string strHost = "api.openweathermap.org";
const std::string strRequest = "/data/2.5/weather?q=BeiJing&appid=c7c9b4。。。你自己的密钥";
class client
{
public:
	client(boost::asio::io_context& io_context,
		const std::string& server, const std::string& path)
		: resolver_(io_context),
		socket_(io_context)
	{
		// 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.
		resolver_.async_resolve(server, "http",
			std::bind(&client::handle_resolve, this,
				boost::asio::placeholders::error,
				boost::asio::placeholders::results));
	}

private:
	void handle_resolve(const boost::system::error_code& err,
		const tcp::resolver::results_type& endpoints)
	{
		if (!err)
		{
			// Attempt a connection to each endpoint in the list until we
			// successfully establish a connection.
			boost::asio::async_connect(socket_, endpoints,
				std::bind(&client::handle_connect, this,
					boost::asio::placeholders::error));
		}
		else
		{
			std::cout << "Error: " << err.message() << "\n";
		}
	}

	void handle_connect(const boost::system::error_code& err)
	{
		if (!err)
		{
			// The connection was successful. Send the request.
			boost::asio::async_write(socket_, request_,
				std::bind(&client::handle_write_request, this,
					boost::asio::placeholders::error));
		}
		else
		{
			std::cout << "Error: " << err.message() << "\n";
		}
	}

	void handle_write_request(const boost::system::error_code& err)
	{
		if (!err)
		{
			// Read the response status line. The response_ streambuf will
			// automatically grow to accommodate the entire line. The growth may be
			// limited by passing a maximum size to the streambuf constructor.
			boost::asio::async_read_until(socket_, response_, "\r\n",
				std::bind(&client::handle_read_status_line, this,
					boost::asio::placeholders::error));
		}
		else
		{
			std::cout << "Error: " << err.message() << "\n";
		}
	}

	void handle_read_status_line(const boost::system::error_code& err)
	{
		if (!err)
		{
			// Check that response is OK.
			std::istream response_stream(&response_);
			std::string http_version;
			response_stream >> http_version;
			unsigned int status_code;
			response_stream >> status_code;
			std::string status_message;
			std::getline(response_stream, status_message);
			if (!response_stream || http_version.substr(0, 5) != "HTTP/")
			{
				std::cout << "Invalid response\n";
				return;
			}
			if (status_code != 200)
			{
				std::cout << "Response returned with status code ";
				std::cout << status_code << "\n";
				return;
			}

			// Read the response headers, which are terminated by a blank line.
			boost::asio::async_read_until(socket_, response_, "\r\n\r\n",
				std::bind(&client::handle_read_headers, this,
					boost::asio::placeholders::error));
		}
		else
		{
			std::cout << "Error: " << err << "\n";
		}
	}

	void handle_read_headers(const boost::system::error_code& err)
	{
		if (!err)
		{
			// Process the response headers.
			std::istream response_stream(&response_);
			std::string header;
			while (std::getline(response_stream, header) && header != "\r")
				std::cout << header << "\n";
			std::cout << "\n";

			// Write whatever content we already have to output.
			if (response_.size() > 0)
				std::cout << &response_;

			// Start reading remaining data until EOF.
			boost::asio::async_read(socket_, response_,
				boost::asio::transfer_at_least(1),
				std::bind(&client::handle_read_content, this,
					boost::asio::placeholders::error));
		}
		else
		{
			std::cout << "Error: " << err << "\n";
		}
	}

	void handle_read_content(const boost::system::error_code& err)
	{
		if (!err)
		{
			// Write all of the data that has been read so far.
			std::cout << &response_;

			// Continue reading remaining data until EOF.
			boost::asio::async_read(socket_, response_,
				boost::asio::transfer_at_least(1),
				std::bind(&client::handle_read_content, this,
					boost::asio::placeholders::error));
		}
		else if (err != boost::asio::error::eof)
		{
			std::cout << "Error: " << err << "\n";
		}
	}

	tcp::resolver resolver_;
	tcp::socket socket_;
	boost::asio::streambuf request_;
	boost::asio::streambuf response_;
};
int main(int argc, char* argv[])
{
	try
	{
		boost::asio::io_context io_context;
		client c(io_context, strHost, strRequest);
		io_context.run();
	}
	catch (std::exception& e)
	{
		std::cout << "Exception: " << e.what() << "\n";
	}

	return 0;
}

服务器返回内容如下(原始字符串):
在这里插入图片描述
3.在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值