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

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#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);
}

你可能感兴趣的:(c语言)