利用阿里云API获取实时天气信息|C语言Linux网络编程练手小项目

文章目录


前言

        在项目开发时常常需要显示各种信息,如时间、天气、温度、空气质量指数等等。嵌入式开发时就经常用到各种API接口了,用来显示或者实现某个模块功能。那么如何获取这些信息呢?本文中用到的为阿里云的API接口,可以由客户端或者SDK调用,本文主要讲解使用客户端调用API接口的方法,带大家编写客户端代码,理解调用原理。 


一、HTTP数据请求

1.HTTP概述

        学过计算机网络的应该都知道HTTP 的基本工作原理是基于网络通信模型中的B/S模型(browser/client),即客户端(通常是 web 浏览器)向服务器发送请求,服务器接收到请求后,返回相应的资源。这些资源可以是网页、图像、音频文件、视频等。返回的资源通常以HTML代码;XML字符串(这在Android开发比较常用);JSON格式这几种形式返回,在对其进行二次处理后成为便于我们在程序中使用的数据。

        本文不对HTTP原理概念阐述过多。需要理解的是要进行HTTP数据请求之前需要进行TCP/IP连接,再发送请求数据报文。就像我们进行网络通信之前必须先进行网络连接,将数据发给服务端,再通过进行应用层通信交换数据。否则数据就不知道要发去哪,发过去或者传过来后该怎么用。这都是这些协议帮我们规定好的。

2.数据请求方式

        本文中使用的HTTP标准为HTTP1.1,在HTTP1.1中 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。下图初步了解一下即可,不需要过多深入。

 

3.JSON格式

        在这个案例中,我们接收到返回的数据为JSON格式,相信大家都遇到过很多该格式的应用,比如vscode很多配置文件都是JSON格式。具体详解可以看下这篇文章 json格式详解-CSDN博客。在很多面向对象语言中都有直接解析JSON格式的类接口,但是由于C语言为本身并不是面向对象的语言所以并没有内置对于该数据格式解析的接口。在这个情况下,衍生出了cJSON,它是一个轻量级,用于处理 JSON 数据的 C 语言库。提供了简单而直观的 API,使得在 C 程序中JSON 数据的处理变得相对容易。

cJSON项目托管在Github上,仓库地址如下:

https://github.com/DaveGamble/cJSON

当然也准备好了网盘供大家下载学习

阿里云盘-cJSON

二、阿里云API获取,使用

1.购买(白嫖)API接口步骤

        进入阿里云后点击上侧导航栏的云市场,搜索万维易源天气。也可以根据图中点击天气预报查询,最上面的便是万维易源实时天气预报查询。

        当然也有其他API接口,不过本次只是一个案例,不需要考虑过多。其他的都是大同小异,后续感兴趣可以尝试一下其他API,还有不同功能都能应用在你的项目中。

        购买(白嫖)步骤省略……

        如图给了很多测试代码,但本文是以C语言编写, 所以不用管。

        

        到了管控中心后(若关闭了需点击云市场回来再点击你的管理工作台),复制好自己的AppCpde,点击右侧的调试。

       

        如图这是我们需要的一些信息,得到这些我们开始写程序。    

2.API使用 代码编写

        首先将下载好的cJSON.c与cJSON.h加入到项目目录中mian.c中便是我们的主程序。

 所要包含的头文件

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>     //下列为socket套接字连接需含的头文件
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

#include "cJSON.h"

#define SERV_PORT 80        //HTTP固定端口为80

获取请求数据

//获取请求数据
char *httpRequest(const char *host)
{
	//堆内存,静态变量,全局变量都行,不能是局部变量
    static char request[1024];
	memset(request, 0, 1024);
	//HTTP请求报文,就是要发给服务端的数据area-to-weather :查询方式
	//%e5%b9%bf%e5%b7%9e:广州的URL编码,网上有在线转换,注意%为转义字符,要输出%需要用%%
	//host:服务端IP,通过gethostbyname函数可将之前拿到的域名转换成对应的IP地址
	//f255********************4ae0:你自己的AppCode
	snprintf(request, 1024, "GET /area-to-weather?area=%%e5%%b9%%bf%%e5%%b7%%9e HTTP/1.1\r\n"
                            "Host: %s\r\n"
                            "Authorization: APPCODE f255********************4ae0\r\n"
                            "\r\n", host);
    return request;
}

TCP连接

int tcp_connect(const char* addr)
{
	int lfd;
	char buf[1024*100] = {0};
	struct hostent *ht = gethostbyname(addr);//根据域名获得IP
	if(ht == NULL){
		perror("gethostbyname");
		exit(0);
	}

    sprintf(buf,"%s", inet_ntoa(*((struct in_addr *)(ht->h_addr_list[0]))));
	printf("解析IP:%s\n",buf);
	
	struct sockaddr_in serv_addr;						//服务器地址结构体
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    //inet_pton(AF_INET, buf, &serv_addr.sin_addr);		//两种方法赋值
	serv_addr.sin_addr = *((struct in_addr *)(ht->h_addr_list[0]));
	
	lfd = socket(AF_INET, SOCK_STREAM, 0);//网络套接字定义
    if (lfd == -1)
	{
		perror("socket error");
		exit(1);
	}
	
	printf("尝试连接...\n");
	//尝试连接网络地址
    int ret = connect(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if (ret != 0)
	{
		perror("connect err");
		exit(1);
	}
	printf("已连接到:%s\n",addr);
	return lfd;
}

主程序

int main(int argc, const char **argv)
{
	//获取命令行参数
	if(argc != 2)
	{
		printf("input error: try 'tianqi3.market.alicloudapi.com'\n");
		exit(0);
	}
	//JOSN解析结构体
	cJSON *js=NULL;
	cJSON *item=NULL;
	cJSON *weather_item=NULL;
	
	char buf[1024*100];
	char j_buf[1024*100];//接收数组
	
	int lfd = tcp_connect(argv[1]);//定义网络套接字并连接服务端
	
	char *s = httpRequest(argv[1]);//获取请求数组
	
	printf("发送请求:%s\n",s);
	write(lfd,s,strlen(s)); //发送请求
	
	read(lfd,buf,sizeof(buf));//获取数据
	//printf("收到报文:%s\n",buf);

	//砍去头部,不然解析会出错
	int j=0,flag=0;
	for(int i=0; i<strlen(buf)+1; i++)
	{
		if(buf[i] == '{' || flag == 1){
			flag = 1;
			j_buf[j] = buf[i];
			j++;
		}
	}
	printf("报文数据:%s\n",j_buf);
	
	printf("解析JOSN数据..\n");
	js = cJSON_Parse(j_buf); //把去头的报文JOSN进行解析
	printf("%s\n",cJSON_Print(js));//打印解析好的报文数据


	/*获取指定数据 层层查找法,要查看JOSN结构名称*/
	item = cJSON_GetObjectItem(js, "showapi_res_body");
	printf("时间:%s\n",cJSON_GetObjectItem(item, "time")->valuestring);
	item = cJSON_GetObjectItem(item, "now");
	weather_item = cJSON_GetObjectItem(item, "aqiDetail");
	//地名查看
	weather_item = cJSON_GetObjectItem(weather_item, "area");
    if(weather_item != NULL){
        printf("地区:%s\n",weather_item->valuestring);
    }
	//天气查看
	weather_item = cJSON_GetObjectItem(item, "weather");
    if(weather_item != NULL){
        printf("天气:%s\n",weather_item->valuestring);
    }
	//温度查看
	weather_item = cJSON_GetObjectItem(item, "temperature");
    if(weather_item != NULL){
        printf("温度: %s℃\n",weather_item->valuestring);
    }
	//风向查看
	weather_item = cJSON_GetObjectItem(item, "wind_direction");
    if(weather_item != NULL){
        printf("风向:%s\n",weather_item->valuestring);
    }
	
    //将json结构占用的数据空间释放
    cJSON_Delete(js);
	//关闭连接
	close(lfd);

	return 0;
}

        程序很简单,需要有一点Linux网络编程的基础,有兴趣的可以看下相关视频


3.编译程序

工具

代码编写:vscode

编译工具:gcc

运行平台:Ubuntu

编译命令:gcc *.c -o client -lm

 域名根据自己所购买的api和所选的请求方式

运行命令:./client tianqi3.market.alicloudapi.com

 4.运行结果

解析IP:47.104.27.167
尝试连接...
已连接到:tianqi3.market.alicloudapi.com
发送请求:GET /area-to-weather?area=%e5%b9%bf%e5%b7%9e HTTP/1.1
Host: tianqi3.market.alicloudapi.com
Authorization: APPCODE f25571f5957f4cda8d0446368ae84ae0


报文数据:{
                  "showapi_res_error": "",
                  "showapi_res_id": "668259adfb638c223b26bce6",
                  "showapi_res_code": 0,
                  "showapi_fee_num": 1,
                  "showapi_res_body": {"time":"20240701120000","cityInfo":{"c4":"guangzhou","c17":"+8","longitude":113.265,"c0":"440100","latitude":23.108,"c7":"广东","c10":"1","c15":"43","c8":"china","c2":"guangzhou","c12":"510000","c5":"广州","c9":"中国","c6":"guangdong","c3":"广州","c11":"020","c16":"AZ9200","c1":"101280101"},"f2":{"day_wind_power":"0-3级 <5.4m/s","night_wind_power":"0-3级 <5.4m/s","night_weather_code":"03","day_weather":"中雨","sun_begin_end":"05:45|19:16","night_weather_pic":"http://app1.showapi.com/weather/icon/night/03.png","day_weather_code":"08","day":"20240702","night_weather":"阵雨","ziwaixian":"最弱","jiangshui":"77%","day_wind_direction":"无持续风向","night_wind_direction":"无持续风向","night_air_temperature":"28","air_press":"1001 hPa","weekday":2,"day_weather_pic":"http://app1.showapi.com/weather/icon/day/08.png","day_air_temperature":"35"},"now":{"wind_direction":"东风","aqi":"31","weather_pic":"http://app1.showapi.com/weather/icon/day/01.png","wind_power":"1级","temperature_time":"15:00","rain":"0.0","weather_code":"01","temperature":"29","sd":"80%","aqiDetail":{"quality":"优质","aqi":"31","pm10":"23","area":"广州","co":"0.5","o3":"73","num":"154","no2":"10","o3_8h":"57","primary_pollutant":"","so2":"4","pm2_5":"13"},"weather":"多云"},"remark":"","f3":{"day_wind_power":"0-3级 <5.4m/s","night_wind_power":"0-3级 <5.4m/s","night_weather_code":"01","day_weather":"阵雨","sun_begin_end":"05:45|19:16","night_weather_pic":"http://app1.showapi.com/weather/icon/night/01.png","day_weather_code":"03","day":"20240703","night_weather":"多云","ziwaixian":"最弱","jiangshui":"71%","day_wind_direction":"无持续风向","night_wind_direction":"无持续风向","night_air_temperature":"27","air_press":"1006.8 hPa","weekday":3,"day_weather_pic":"http://app1.showapi.com/weather/icon/day/03.png","day_air_temperature":"35"},"ret_code":0,"f1":{"day_wind_power":"0-3级 <5.4m/s","night_wind_power":"0-3级 <5.4m/s","night_weather_code":"04","day_weather":"雷阵雨","sun_begin_end":"05:44|19:16","night_weather_pic":"http://app1.showapi.com/weather/icon/night/04.png","day_weather_code":"04","day":"20240701","night_weather":"雷阵雨","ziwaixian":"最弱","jiangshui":"85%","day_wind_direction":"无持续风向","night_wind_direction":"无持续风向","night_air_temperature":"28","air_press":"999.6 hPa","weekday":1,"day_weather_pic":"http://app1.showapi.com/weather/icon/day/04.png","day_air_temperature":"35"}}

                }
                

0


解析JOSN数据..
{
        "showapi_res_error":    "",
        "showapi_res_id":       "668259adfb638c223b26bce6",
        "showapi_res_code":     0,
        "showapi_fee_num":      1,
        "showapi_res_body":     {
                "time": "20240701120000",
                "cityInfo":     {
                        "c4":   "guangzhou",
                        "c17":  "+8",
                        "longitude":    113.265000,
                        "c0":   "440100",
                        "latitude":     23.108000,
                        "c7":   "广东",
                        "c10":  "1",
                        "c15":  "43",
                        "c8":   "china",
                        "c2":   "guangzhou",
                        "c12":  "510000",
                        "c5":   "广州",
                        "c9":   "中国",
                        "c6":   "guangdong",
                        "c3":   "广州",
                        "c11":  "020",
                        "c16":  "AZ9200",
                        "c1":   "101280101"
                },
                "f2":   {
                        "day_wind_power":       "0-3级 <5.4m/s",
                        "night_wind_power":     "0-3级 <5.4m/s",
                        "night_weather_code":   "03",
                        "day_weather":  "中雨",
                        "sun_begin_end":        "05:45|19:16",
                        "night_weather_pic":    "http://app1.showapi.com/weather/icon/night/03.png",
                        "day_weather_code":     "08",
                        "day":  "20240702",
                        "night_weather":        "阵雨",
                        "ziwaixian":    "最弱",
                        "jiangshui":    "77%",
                        "day_wind_direction":   "无持续风向",
                        "night_wind_direction": "无持续风向",
                        "night_air_temperature":        "28",
                        "air_press":    "1001 hPa",
                        "weekday":      2,
                        "day_weather_pic":      "http://app1.showapi.com/weather/icon/day/08.png",
                        "day_air_temperature":  "35"
                },
                "now":  {
                        "wind_direction":       "东风",
                        "aqi":  "31",
                        "weather_pic":  "http://app1.showapi.com/weather/icon/day/01.png",
                        "wind_power":   "1级",
                        "temperature_time":     "15:00",
                        "rain": "0.0",
                        "weather_code": "01",
                        "temperature":  "29",
                        "sd":   "80%",
                        "aqiDetail":    {
                                "quality":      "优质",
                                "aqi":  "31",
                                "pm10": "23",
                                "area": "广州",
                                "co":   "0.5",
                                "o3":   "73",
                                "num":  "154",
                                "no2":  "10",
                                "o3_8h":        "57",
                                "primary_pollutant":    "",
                                "so2":  "4",
                                "pm2_5":        "13"
                        },
                        "weather":      "多云"
                },
                "remark":       "",
                "f3":   {
                        "day_wind_power":       "0-3级 <5.4m/s",
                        "night_wind_power":     "0-3级 <5.4m/s",
                        "night_weather_code":   "01",
                        "day_weather":  "阵雨",
                        "sun_begin_end":        "05:45|19:16",
                        "night_weather_pic":    "http://app1.showapi.com/weather/icon/night/01.png",
                        "day_weather_code":     "03",
                        "day":  "20240703",
                        "night_weather":        "多云",
                        "ziwaixian":    "最弱",
                        "jiangshui":    "71%",
                        "day_wind_direction":   "无持续风向",
                        "night_wind_direction": "无持续风向",
                        "night_air_temperature":        "27",
                        "air_press":    "1006.8 hPa",
                        "weekday":      3,
                        "day_weather_pic":      "http://app1.showapi.com/weather/icon/day/03.png",
                        "day_air_temperature":  "35"
                },
                "ret_code":     0,
                "f1":   {
                        "day_wind_power":       "0-3级 <5.4m/s",
                        "night_wind_power":     "0-3级 <5.4m/s",
                        "night_weather_code":   "04",
                        "day_weather":  "雷阵雨",
                        "sun_begin_end":        "05:44|19:16",
                        "night_weather_pic":    "http://app1.showapi.com/weather/icon/night/04.png",
                        "day_weather_code":     "04",
                        "day":  "20240701",
                        "night_weather":        "雷阵雨",
                        "ziwaixian":    "最弱",
                        "jiangshui":    "85%",
                        "day_wind_direction":   "无持续风向",
                        "night_wind_direction": "无持续风向",
                        "night_air_temperature":        "28",
                        "air_press":    "999.6 hPa",
                        "weekday":      1,
                        "day_weather_pic":      "http://app1.showapi.com/weather/icon/day/04.png",
                        "day_air_temperature":  "35"
                }
        }
}
时间:20240701120000
地区:广州
天气:多云
温度: 29℃
风向:东风

总结

        案例中涉及到许多网络相关的知识,如果大家对其中的步骤不懂,欢迎大家提问。若或者有写的有不清晰或者错误,欢迎指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值