需求分析:
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 这我就不填。。。
![这里写图片描述](http://img.blog.csdn.net/20170815164731926?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQ29taW5nRmx5aW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
相关代码:

#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网络编程之"获取网络天气信息"的更多相关文章

  1. 循序渐进Socket网络编程(多客户端、信息共享、文件传输)

    循序渐进Socket网络编程(多客户端.信息共享.文件传输) 前言:在最近一个即将结束的项目中使用到了Socket编程,用于调用另一系统进行处理并返回数据.故把Socket的基础知识总结梳理一遍. 1 ...

  2. 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    [Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...

  3. c/c++ 网络编程 UDP 主机网络信息取得

    网络编程 UDP 主机网络信息取得 1,if_nametoindex 通过网卡名字取得网卡编号 2,if_indextoname 通过网卡编号取得网卡名字 #include <stdio.h&g ...

  4. C# 通过豆瓣网络编程API获取图书信息

    这篇文章主要是关于如何通过豆瓣API获取信息的书籍,起初,我看到了原来的想法的内容是"C# 网络编程之网页简单下载实现"中通过HttpWebResponse类下载源代码,再通过正則 ...

  5. 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)

    目录[-] 一.TCP/IP协议 二.TCP与UDP 三.Socket是什么 四.Java中的Socket 五.基本的Client/Server程序 六.多客户端连接服务器 七.信息共享 八.文件传输 ...

  6. 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...

  7. Linux系统编程:socket网络编程(操作篇)

    一.问题思考 问1.网络通信应用在什么场合?通信的前提是什么? 答1.主要应用在不同主机进程间的互相通信,同一主机的进程也可以使用网络进行通信.通信的前提是如何标识通信进程的唯一,由于不同主机的进程极 ...

  8. Python3 与 C# 网络编程之~ 网络基础篇

    最新版本查看:https://www.cnblogs.com/dotnetcrazy/p/9919202.html 入门篇 官方文档:https://docs.python.org/3/library ...

  9. 【网络编程4】网络编程基础-ARP响应(ARP欺骗之中间人攻击)

    arp欺骗->arp响应 ARP 缓存中毒(ARP欺骗) arp传送原理在于主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址:收到返回消 ...

随机推荐

  1. Vue中的指令(听博主说总结的很好)

    指令[重点] 作用:简化Dom操作 参考:https://cn.vuejs.org/v2/api/#%E6%8C%87%E4%BB%A4 特点: 1.都是以v-开头 2.除了插值表达式,其它都写在标签 ...

  2. JS——制作简单的网页计算器

    用JS做了一个简易的网页计算器 <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  3. upper_bound和lower_bound的用法

    首先介绍这两种函数是什么意思 upper_bound是找到大于t的最小地址,如果没有就指向末尾 lower_bound是找到大于等于t的最小地址 题目链接:https://vjudge.net/con ...

  4. Unity在Project视图里面显示文件的拓展名

    Unity在Project视图里面显示文件的拓展名 功能脚本如下: using System.IO; using System.Reflection; using UnityEngine; using ...

  5. Asp.NetCore WebApi 引入Swagger

    一.创建一个Asp.NetCore WebApi 项目 二.引入NuGet包 SwashBuckle.AspNetCore 三.在项目属性配置中设置 四.修改项目的启动文件Startup.cs 1). ...

  6. IDEA使用汇总

    1. 常用配置 File --> Settings (Ctrl + Alt + S) 1).提示不区分大小写: Editor-->Genereal-->Code Completion ...

  7. pat1078. Hashing (25)

    1078. Hashing (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue The task of t ...

  8. ORA-02298: 无法验证 (约束) - 未找到父项关键字 解决办法

    --在用PL/SQL导入表数据的时候报错 ORA-02298: 无法验证 (PNET.POST_CLOB_FK) - 未找到父项关键字 --发现是启用外键约束时报的错alter table DM_VO ...

  9. 360或其他双核浏览器下在兼容模式用chrome内核渲染的方法

    <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-COM ...

  10. CentOS6.5 环境安装配置

    一.GO环境配置 1.运行命令进入/usr/local/src目录:cd /usr/local/src 2.下载安装包:运行wget --no-check-certificate https://st ...