Linux网络编程之"获取网络天气信息"
需求分析:
1.需要Linux c 网络编程基础,
2.需要了解 http 协议
3.需要天气信息相关api(可以从阿里云上购买,很便宜的!)
4.需要cJSON解析库(因为获取到的天气信息一般是用cJSON
封装,有的是用xml封装则需要相关解析库)
cJSON下载链接:https://github.com/DaveGamble/cJSON
cJSON在线代码格式化:http://tool.oschina.net/codeformat/json
cJSON简解及使用:
cJSON核心结构体:
typedef struct cJSON
{
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type; /*键类型*/
char *valuestring; /*字符串值*/
int valueint; /*整形值*/
double valuedouble; /*浮点值*/
char *string; /*键名称*/
} cJSON;
说明:cJSON数据是以(键-值)形式存在。每个键对应的值都可以
访问(valuestring、valueint、valuedouble)成员得到。
主要用到的函数:
1. CSJON_PUBLIC(cJSON*) cJSON_Parse(const char *value);
用了获得根节点,
2. CSJON_PUBLIC(cJSON*) cJSON_GetObjectItem(const cJSON* const object, const char *const string);
用来获得根节点下的子节点,
3. CSJON_PUBLIC(void) cJSON_Delete(const cJSON *item);
用来释放为根节点分配的内存!
获取天气的http协议:
"GET /phone-post-code-weeather?"
"phone_code=021 "
"HTTP/1.1\r\n"
"Host:ali-weather.showapi.com\r\n"
"Authorization:APPCODE xxxxxx\r\n\r\n"
解释说明:
"/phone-post-code-weeather"此部分对应于 path格式
"Host:ali-weather.showapi.com"此部分对应于 接口域名
"phone_code" 表示城市编号021为上海(记住后面要空格)
"xxxxxx" 为你购买的APPCODE 这我就不填。。。

相关代码:
#include <netdb.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include "common.h"
#include "cJSON.h"
#define SERV_PORT 80
typedef struct sockaddr SA;
void http_request(char *buf, int size, char *city_name);
void analyze_CJSON(const char *json);
char *recv_msg(int sockfd);
int main(int argc, char **argv)
{
int sockfd;
struct hostent *hptr = NULL;
struct sockaddr_in servaddr;
struct in_addr **pptr;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
err_quit("socket error");
}
char *alias_name = "ali-weather.showapi.com";
//char *alias_name = "jisutianqi.market.alicloudapi.com";
//得到接口域名的IP地址
if ((hptr = gethostbyname(alias_name)) == NULL) {
err_quit("gethostbyname error for host: %s: %s",
alias_name, hstrerror(h_errno));
}
pptr = (struct in_addr **)hptr->h_addr_list;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));
if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) {
err_quit("connect error");
}
char buf[MAXLINE];
//设置想要查询的城市编号,也可以安其他方式查询
char *phone_code = "021";
http_request(buf, MAXLINE, phone_code);
//发送http请求
if (write(sockfd, buf, strlen(buf)) != strlen(buf)) {
err_quit("write error");
}
//接收返回信息
char *json = recv_msg(sockfd);
//解析CJSON数据
analyze_CJSON(json);
return EXIT_SUCCESS;
}
void http_request(char *buf, int size, char *phone_code)
{
bzero(buf, size);
snprintf(buf, size, "GET /phone-post-code-weeather?"
"phone_code=%s "
"HTTP/1.1\r\n"
//"Host:jisutianqi.market.alicloudapi.com\r\n"
"Host:ali-weather.showapi.com\r\n"
"Authorization:APPCODE d487d937315848af80710a06f4592fee\r\n\r\n"
, phone_code);
}
/**
*注意:返回的信息包含http报头信息和实际的CJSON数据,我们只
*需要CJSON数据,所有需要做一定处理。
**/
char * recv_msg(int sockfd)
{
int nread;
char recvbuf[4096];
char *begin = NULL, *end = NULL;
char *lenght = NULL;
char *data = NULL;
char tar[] = "Content-Length: ";
bool flage = true;
while (1) {
bzero(recvbuf, sizeof(recvbuf));
if ((nread = read(sockfd, recvbuf, sizeof(recvbuf))) == 0) {
break;
}
//获得cJSON数据的字节数,存储到lenght中,并调用atoi函数将其转化为int类型
if (strstr(recvbuf, "403") != NULL || strstr(recvbuf, "Quota Exhausted")) {
err_quit("your appcode is expire..");
}
if (flage) {
if ((begin = strstr(recvbuf, tar)) != NULL) {
if ((end = strstr(begin, "\r\n")) != NULL) {
lenght = malloc(end - (begin+strlen(tar)));
memcpy(lenght, begin+strlen(tar), end-(begin+strlen(tar)));
data = calloc(1, atoi(lenght));
if (data == NULL) {
err_quit("malloc error");
}
strcpy(data, strrchr(recvbuf, '\n')+1);
}
} else {
continue;
}
}
if (!flage) {
strcat(data, recvbuf);
}
if (strlen(data) == atoi(lenght)) {
break;
}
flage = false;
}
printf("atoi(lenght) = %d\n", atoi(lenght));
free(lenght);
return data;
}
void analyze_CJSON(const char *json)
{
//获得根节点
cJSON *root = cJSON_Parse(json);
if (root == NULL) {
err_quit("cJSON_Parse error");
}
cJSON *body = cJSON_GetObjectItem(root, "showapi_res_body");
if (body == NULL) {
err_quit("body error");
}
//判断是否成功得到数据
if (cJSON_GetObjectItem(body, "ret_code")->valueint == -1) {
err_quit("json data invalid..");
}
cJSON *now = cJSON_GetObjectItem(body, "now");
if (now == NULL) {
err_quit("get now failure");
}
cJSON *aqiDetai = cJSON_GetObjectItem(now, "aqiDetail");
if (aqiDetai == NULL) {
err_quit("get aqiDetai failure");
}
cJSON *cityinfo = cJSON_GetObjectItem(body, "cityInfo");
if (cityinfo == NULL) {
err_quit("get cityinfo failure");
}
cJSON *f1 = cJSON_GetObjectItem(body, "f1");
if (f1 == NULL) {
err_quit("get f1 failure");
}
cJSON *f2 = cJSON_GetObjectItem(body, "f2");
if (f1 == NULL) {
err_quit("get f2 failure");
}
cJSON *f3 = cJSON_GetObjectItem(body, "f3");
if (f1 == NULL) {
err_quit("get f3 failure");
}
printf(" country:\t%s\n", cJSON_GetObjectItem(cityinfo, "c9")->valuestring);
printf(" area:\t%s\n", cJSON_GetObjectItem(aqiDetai, "area")->valuestring);
printf(" quality:\t%s\n", cJSON_GetObjectItem(aqiDetai, "quality")->valuestring);
printf(" pm2_5:\t%s\n", cJSON_GetObjectItem(aqiDetai, "pm2_5")->valuestring);
printf(" pm10:\t%s\n", cJSON_GetObjectItem(aqiDetai, "pm10")->valuestring);
printf(" aqi:\t%s\n", cJSON_GetObjectItem(aqiDetai, "aqi")->valuestring);
printf("\ntoday weather:\n");
printf(" day_weather:\t%s\n", cJSON_GetObjectItem(f1, "day_weather")->valuestring);
printf(" day_wind_power:\t%s\n", cJSON_GetObjectItem(f1, "day_wind_power")->valuestring);
printf(" day_wind_direction:\t%s\n", cJSON_GetObjectItem(f1, "day_wind_direction")->valuestring);
printf("day_air_temperature:\t%s\n", cJSON_GetObjectItem(f1, "day_air_temperature")->valuestring);
printf("\ntomorrow weather:\n");
printf(" day_weather:\t%s\n", cJSON_GetObjectItem(f2, "day_weather")->valuestring);
printf(" day_wind_power:\t%s\n", cJSON_GetObjectItem(f2, "day_wind_power")->valuestring);
printf(" day_wind_direction:\t%s\n", cJSON_GetObjectItem(f2, "day_wind_direction")->valuestring);
printf("day_air_temperature:\t%s\n", cJSON_GetObjectItem(f2, "day_air_temperature")->valuestring);
printf("\nthe day after tomorrow weather:\n");
printf(" day_weather:\t%s\n", cJSON_GetObjectItem(f3, "day_weather")->valuestring);
printf(" day_wind_power:\t%s\n", cJSON_GetObjectItem(f3, "day_wind_power")->valuestring);
printf(" day_wind_direction:\t%s\n", cJSON_GetObjectItem(f3, "day_wind_direction")->valuestring);
printf("day_air_temperature:\t%s\n", cJSON_GetObjectItem(f3, "day_air_temperature")->valuestring);
cJSON_Delete(root);
}
Linux网络编程之"获取网络天气信息"的更多相关文章
- 循序渐进Socket网络编程(多客户端、信息共享、文件传输)
循序渐进Socket网络编程(多客户端.信息共享.文件传输) 前言:在最近一个即将结束的项目中使用到了Socket编程,用于调用另一系统进行处理并返回数据.故把Socket的基础知识总结梳理一遍. 1 ...
- 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
[Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...
- c/c++ 网络编程 UDP 主机网络信息取得
网络编程 UDP 主机网络信息取得 1,if_nametoindex 通过网卡名字取得网卡编号 2,if_indextoname 通过网卡编号取得网卡名字 #include <stdio.h&g ...
- C# 通过豆瓣网络编程API获取图书信息
这篇文章主要是关于如何通过豆瓣API获取信息的书籍,起初,我看到了原来的想法的内容是"C# 网络编程之网页简单下载实现"中通过HttpWebResponse类下载源代码,再通过正則 ...
- 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)
目录[-] 一.TCP/IP协议 二.TCP与UDP 三.Socket是什么 四.Java中的Socket 五.基本的Client/Server程序 六.多客户端连接服务器 七.信息共享 八.文件传输 ...
- 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...
- Linux系统编程:socket网络编程(操作篇)
一.问题思考 问1.网络通信应用在什么场合?通信的前提是什么? 答1.主要应用在不同主机进程间的互相通信,同一主机的进程也可以使用网络进行通信.通信的前提是如何标识通信进程的唯一,由于不同主机的进程极 ...
- Python3 与 C# 网络编程之~ 网络基础篇
最新版本查看:https://www.cnblogs.com/dotnetcrazy/p/9919202.html 入门篇 官方文档:https://docs.python.org/3/library ...
- 【网络编程4】网络编程基础-ARP响应(ARP欺骗之中间人攻击)
arp欺骗->arp响应 ARP 缓存中毒(ARP欺骗) arp传送原理在于主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址:收到返回消 ...
随机推荐
- 才知道 Windows Live Writer Source Code plugin for SyntaxHighlighter 更新到2.0了
这是我用 Windows Live Writer 发布的第一篇文章! 在官方网站看到 Windows Live Writer Source Code plugin for SyntaxHighligh ...
- 文件系统满的话(filesystem full),该如何处理。(du and ls)
#!/bin/bash function ergodic(){ ` do "/"$file ] then ergodic $"/"$file else loca ...
- Spring学习(五)事务管理
Spring 事务管理: 一.事务概念: 1.什么是事务? 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的 ...
- 【Unity3D/C#】Unity3D中的Coroutine详解
Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...
- java多线程,如何防止脏读数据
多线程容易“非线程安全”的情况,是由于用了全局变量,而又没有很好的控制起情况.所以无论做什么程序,谨慎使用全局变量 "非线程安全"其实会在多个线程对同一个对象中的实例变量进行并发访 ...
- HDU 5501——The Highest Mark——————【贪心+dp】
The Highest Mark Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
- XShell远程连接本地虚机
有很多朋友在自己电脑上部署完成了虚机,但是不知道怎么去用工具连接自己的虚机,下面给大家讲一下大概的步骤,不足之处敬请指正!! 1.打开我们的虚拟机平台,登录虚机 2.远程那肯定要知道虚机的IP地址,在 ...
- WPF动画的几种模式
最近在用WPF做简单动画,以下是几点经验总结: 1. 使用DispatcherTimer做动画 VB6的年代大家就用Timer做动画了,不用多解释,这个DispatcherTimer和本身的Timer ...
- html5 知识总结
Meta基础知识: H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 //一.HTML页面结构<meta name="viewport" content=" ...
- oracle 清空数据库缓存
oracle 清除数据库缓存: alter system flush shared_pool ; alter system flush BUFFER_CACHE ;