需求分析:
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. 才知道 Windows Live Writer Source Code plugin for SyntaxHighlighter 更新到2.0了

    这是我用 Windows Live Writer 发布的第一篇文章! 在官方网站看到 Windows Live Writer Source Code plugin for SyntaxHighligh ...

  2. 文件系统满的话(filesystem full),该如何处理。(du and ls)

    #!/bin/bash function ergodic(){ ` do "/"$file ] then ergodic $"/"$file else loca ...

  3. Spring学习(五)事务管理

    Spring 事务管理: 一.事务概念: 1.什么是事务? 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的 ...

  4. 【Unity3D/C#】Unity3D中的Coroutine详解

    Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...

  5. java多线程,如何防止脏读数据

    多线程容易“非线程安全”的情况,是由于用了全局变量,而又没有很好的控制起情况.所以无论做什么程序,谨慎使用全局变量 "非线程安全"其实会在多个线程对同一个对象中的实例变量进行并发访 ...

  6. HDU 5501——The Highest Mark——————【贪心+dp】

    The Highest Mark Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  7. XShell远程连接本地虚机

    有很多朋友在自己电脑上部署完成了虚机,但是不知道怎么去用工具连接自己的虚机,下面给大家讲一下大概的步骤,不足之处敬请指正!! 1.打开我们的虚拟机平台,登录虚机 2.远程那肯定要知道虚机的IP地址,在 ...

  8. WPF动画的几种模式

    最近在用WPF做简单动画,以下是几点经验总结: 1. 使用DispatcherTimer做动画 VB6的年代大家就用Timer做动画了,不用多解释,这个DispatcherTimer和本身的Timer ...

  9. html5 知识总结

    Meta基础知识:  H5页面窗口自动调整到设备宽度,并禁止用户缩放页面    //一.HTML页面结构<meta name="viewport" content=" ...

  10. oracle 清空数据库缓存

    oracle 清除数据库缓存: alter system flush shared_pool ; alter system flush BUFFER_CACHE ;