首页 > 编程语言 >基于HTTP传输协议、cJSON库的网络天气获取程序

基于HTTP传输协议、cJSON库的网络天气获取程序

时间:2024-06-12 10:14:43浏览次数:29  
标签:HTTP cli cJSON errno 传输 client inf buf

基于HTTP传输协议、cJSON库的网络天气获取程序


#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include "cJSON.h"                          //cJSON头文件

#define SERV_PORT   80                      //http端口号
#define CLI_PORT    8888                    //本地端口号
#define CLI_IP      "172.23.60.138"         //本地IP
#define DOMAIN_NAME "api.seniverse.com"     //域名
#define KEY         "SzIYujfNSBeee1MPr"     //密钥
#define LOCATION    "guangzhou"             //地区
#define LANGUAGE    "zh-Hans"               //语言
#define MAX_IP_LEN  16                      //IP长度

//常用数据结构体
typedef struct client_information
{
    char ip[MAX_IP_LEN];    //域名对应IP
    int sock_fd;            //套接字
    struct cJSON *root;     //cJSON格式的根对象指针
}client_inf, *client_inf_p;


// JSON结构体
// typedef struct cJSON 
// {
//     struct cJSON *next,*prev;	
//     struct cJSON *child;		   	//树状结构
//     int type;					//值的类型
//     char *valuestring;			//字符串类型的值
//     int valueint;				//整型类型的值
//     double valuedouble;			//浮点类型的值
//     char *string;				//"name"
// } cJSON;


int Client_Link(client_inf_p cli_inf);      //客户端连接服务器函数
void Get_Weather(client_inf_p cli_inf);     //从服务器获取天气信息并转换成cJSON格式
void Parse_cJSON(client_inf_p cli_inf);     //解析cJSON格式信息


int main(int argc, char *argv[])
{
    //定义并为常用信息结构体申请堆空间
    client_inf_p cli_inf = (client_inf_p)malloc(sizeof(client_inf));
    if (cli_inf == NULL)
    {
        fprintf(stderr, "malloc error,errno:%d,%s", errno, strerror(errno));
        exit(-1);
    }
    bzero(cli_inf, sizeof(client_inf));

    Client_Link(cli_inf);

    Get_Weather(cli_inf);

    Parse_cJSON(cli_inf);

    return 0;
}

//客户端连接服务器函数
int Client_Link(client_inf_p cli_inf)
{
    //socket获取套接字
    if ((cli_inf->sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        fprintf(stderr, "socket error, errno:%d,%s", errno, strerror(errno));
        exit(-1);
    }

    struct sockaddr_in cliaddr;
    bzero(&cliaddr, sizeof(cliaddr));

    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(CLI_PORT);
    cliaddr.sin_addr.s_addr = inet_addr(CLI_IP);

    //绑定套接字
    if (bind(cli_inf->sock_fd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) == -1)
    {
        fprintf(stderr, "bind error, errno:%d,%s", errno, strerror(errno));
        exit(-1);
    }

    struct sockaddr_in servaddr;    //定义服务器IP信息结构体
    struct sockaddr_in tmpaddr;     //定义一个信息结构体接收域名IP
    bzero(&servaddr, sizeof(servaddr));

    struct hostent *host_inf = gethostbyname(DOMAIN_NAME);  //定义并获取域名信息结构体
    if (host_inf == NULL)
    {
        fprintf(stderr, "gethostbyname error,errno:%d,%s", errno, strerror(errno));
        exit(-1);
    }

    memcpy(&tmpaddr.sin_addr, host_inf->h_addr, sizeof(struct in_addr));    //将网络字节序复制给sin_addr,方便后续inet_ntoa函数的字符串转换
    strcpy(cli_inf->ip, inet_ntoa(tmpaddr.sin_addr));                       //赋值常用结构体中IP

    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    servaddr.sin_addr.s_addr = inet_addr(cli_inf->ip);

    //开始连接服务器
    if (connect(cli_inf->sock_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)    
    {
        fprintf(stderr, "connect error,errno:%d,%s", errno, strerror(errno));
        exit(-1);
    }

    printf("connect success!\n\n");

    return 0;
}

//从服务器获取天气信息并转换成cJSON格式
void Get_Weather(client_inf_p cli_inf)
{
    char buf[1024] = "\0";
    
    //拼接http数据包
    sprintf(buf, "GET https://%s/v3/weather/now.json?key=%s&location=%s&language=%s&unit=c HTTP/1.1\r\n"
                 "Host:api.seniverse.com\r\n"
                 "\r\n", 
                 DOMAIN_NAME, KEY, LOCATION, LANGUAGE
            );

    //发送数据包
    if (send(cli_inf->sock_fd, buf, strlen(buf), 0) == -1)
    {
        fprintf(stderr, "send error,errno:%d,%s", errno, strerror(errno));
        exit(-1);
    }

    bzero(buf, sizeof(buf));
    //接收服务器应答信息
    if (recv(cli_inf->sock_fd, buf, sizeof(buf), 0) == -1)
    {
        fprintf(stderr, "recv error,errno:%d,%s", errno, strerror(errno));
        exit(-1);
    }

    bzero(buf, sizeof(buf));
    //接收服务器发送的数据
    if (recv(cli_inf->sock_fd, buf, sizeof(buf), 0) == -1)
    {
        fprintf(stderr, "recv error,errno:%d,%s", errno, strerror(errno));
        exit(-1);
    }

    //保存cJSON格式的根对象指针
    cli_inf->root = cJSON_Parse(buf);
}

//解析cJSON格式信息
void Parse_cJSON(client_inf_p cli_inf)
{
    char weather_msg[100] = "\0";
    //第一层解析
    cJSON * results     = cJSON_GetObjectItem(cli_inf->root, "results");
    //第二层解析
    cJSON * obj         = cJSON_GetArrayItem(results, 0);
    //第三次解析
    cJSON * location    = cJSON_GetObjectItem(obj, "location");
    cJSON * now         = cJSON_GetObjectItem(obj, "now");
    //第四层解析
    cJSON * name        = cJSON_GetObjectItem(location, "name");
    //第四层解析
    cJSON * text        = cJSON_GetObjectItem(now, "text");
    cJSON * temperature = cJSON_GetObjectItem(now, "temperature");
    
    //获取并拼接所需数据
    sprintf(weather_msg, "城市:%s\n天气:%s\n温度:%s\n", name->valuestring, text->valuestring, temperature->valuestring);

    //输出信息
    printf("%s\n", weather_msg);
}

标签:HTTP,cli,cJSON,errno,传输,client,inf,buf
From: https://www.cnblogs.com/colors-lg/p/18243375

相关文章

  • HTTP协议
    1.HTTP协议简介服务器和客户端相互通信所遵守的规则遵守HTTP协议发送的数据称作报文客户端给服务器发送数据—请求(GET请求和POST请求)服务器给客户端发送数据—响应HTTP协议是无状态的,会将每次浏览器的请求,视为一次新的请求。这样设计的原因是由于,如果每次请求都将记录上......
  • 五大步骤教你轻松实现企业网站HTTPS访问
    企业网站实现HTTPS访问主要涉及以下方法和流程:一、选择合适的SSL证书:根据企业需求选择合适的SSL证书类型。DV(域名验证)证书适用于个人网站和小企业,验证过程简单,只需证明对域名的控制权。OV(组织验证)和EV(扩展验证)证书则提供更高层次的信任,适用于希望提升网站形象和安全性的企业......
  • HTTP和HTTPS
    [TOP]HTTP和HTTPS的基本概念HTTP:超文本传输协议(HTTP,HyperTextTransferProtocol)是互联网上应用最为广泛的一种网络协议。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。它可以使浏览器更加高效。HTTP协议是以明文方式发送信息的,如果黑客截取了Web浏览......
  • http与cJSON练习
    http与cJSON练习/*****************************************************************************************************weather_test.c*练习tcp连接,与http协议,调用服务器接口,实现获取特定城市的天气信息,并用cJSO......
  • 利用聚合API平台的API接口,利用HTTP协议向服务器发送请求,并接受服务器的响应,要求利用cJ
    目录题目分析代码结果题目利用聚合API平台的API接口,利用HTTP协议向服务器发送请求,并接受服务器的响应,要求利用cJSON库对服务器的响应数据进行解析,并输出到终端分析1.需从源代码网站GitHub或SourceForge代码网站下载cJSON库及阅读下载的README相关手册如何使用cJSON库;2.使用......
  • 网络编程练习题---利用cJSON库对服务器返回的JSON格式数据完成解析
    目录题目注意事项实现代码结果展示相关接口指引题目利用某些平台(聚合API、百度AI、科大讯飞API)的API接口,利用HTTP协议向服务器发送请求,并接受服务器的响应,要求利用cJSON库对服务器的响应数据进行解析,并输出到终端。注意事项1.预测的日期开始时间为2010-01-012."老黄历"API......
  • cJSON学习及简单应用小结
    JSON简介JSON(JavaScriptObjectNotation,JavaScript对象表示法)是一种轻量级的数据交换格式。它基于ECMAScript(欧洲计算机制造商协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON成为理想的数据交换语言。以下是JSON......
  • 基于centos7.9搭建http文件服务器
    基于centos7.9搭建http文件服务器1.安装httpd[root@localhost~]#yuminstall-yhttpd2.关闭防火墙以及selinux[root@localhost~]#systemctlstopfirewalld&&setenforce03.修改相关配置​ 文件/etc/httpd/conf/httpd.conf中的默认参数(自定义修改)[root@loca......
  • 卫星通讯传输技术助力电力运维巡检效率提升:EasyCVR实现远程监控与管理的新路径
    随着科技的快速发展,视频监控技术已广泛应用于各个领域。而卫星通讯作为一种高效、稳定的通信方式,为视频监控系统的远程传输提供了有力支持。一、方案背景随着电力行业的快速发展,电力运维巡检工作变得愈发重要。传统的巡检方式往往受到地域、环境等因素的限制,难以实现对电力设备......
  • CTFHUB技能树之WEB前置技能HTTP协议
    CTFHUB技能树WEB前置技能/HTTP协议请求方式根据提示可知,通过修改请求方式获取flag使用BurpSuite进行拦截,将GET方法改为CTFHUB方法即可。得到flag。302跳转打开BurpSuite进行拦截,将第一次请求发给重发器再次发送,得出flagCookie打开页面,得出提示信息,需要admin,将Cook......