网络编程练习题---利用cJSON库对服务器返回的JSON格式数据完成解析

news/2024/10/5 3:21:58

目录
  • 题目
    • 注意事项
    • 实现代码
    • 结果展示
    • 相关接口指引

题目


利用某些平台(聚合API、百度AI、科大讯飞API)的API接口,利用HTTP协议向服务器发送请求,并接受服务器的响应,要求利用cJSON库对服务器的响应数据进行解析,并输出到终端。

注意事项

1.预测的日期开始时间为2010-01-01

2."老黄历"API 服务器返回值是将响应包体与响应行一同返回,所以该程序只需要对服务器返回值接收一次,再利用strstr进行找寻响应包体,最后完成JASON格式数据的解析,但是,这种返回方式不是固定的。例如:“天气预报”API返回数据将响应行与响应包体分为两次发出,所以需要接收两次。

3.该程序代码使用了cJSON库,所以需要用户提前下载并将cJSON.c和cJSON.h加入程序文档。

实现代码

/********************************************************************************
*
*	file name:	demo.c
*	author	 :  ProgramMonkey_Fly@126.com 
*	date	 :  2024/06/11
*	function :  
*               该案例是学习掌握对JSON格式服务器响应数据的解析与构造
*				使用“聚合数据”官网提供的免费接口“老黄历”作为学习例子
* 	note	 :  
*				1.预测的日期开始时间为2010-01-01
*				2."老黄历"API 服务器返回值是将响应包体与响应行一同返回,所以该程序只需要
*					对服务器返回值接收一次,再利用strstr进行找寻响应包体,最后完成JASON
*					格式数据的解析,但是,这种返回方式不是固定的。例如:“天气预报”API返回
*					数据将响应行与响应包体分为两次发出,所以需要接收两次。
*				3.该程序代码使用了cJSON库,所以需要用户提前下载并将cJSON.c和cJSON.h加入
*					程序文档。
*   version  :
*
*	CopyRight (c)  2023-2024   ProgramMonkey_Fly@126.com   All Right Reseverd 
*
* ******************************************************************************/
/****************************头文件*********************************************/
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/select.h>
#include "cJSON.h"
#include <string.h>/****************************宏定义*********************************************/
#define HOST "v.juhe.cn"              					  //服务器域名
#define PORT 80                       					  //http协议端口号
#define BUFSIZE 4096                   					  //自定义缓冲区大小
#define KEY  "..."			 							  //API需要的密钥(在个人中心->我的数据,接口名称上方查看)
#define DATE "2024-06-12"								  //想要预测日期,格式2014-09-09int main(int argc, char **argv)
{//创建TCP的套接字文件int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);if(tcp_socket == -1){fprintf(stderr, "tcp socket error,errno:%d,%s\n",errno,strerror(errno));exit(1);}//向服务器发送请求之前,需要设置目标端口和目标地址struct sockaddr_in  dest_addr;socklen_t flag_dest = sizeof(dest_addr);dest_addr.sin_family 		= AF_INET; 						//协议族,是固定的dest_addr.sin_port   		= htons(PORT);			//服务器运行进程的端口号,必须转换为网络字节序//利用gethostbyname函数接口,获取服务器域名所包含的信息---即获取服务器的ipstruct hostent *hostent =  gethostbyname(HOST);if(hostent == NULL){fprintf(stderr, "ip get error,errno:%d,%s\n",errno,strerror(errno));exit(2);}//存储服务器IP地址,必须转换为点分十进制字符串形式dest_addr.sin_addr.s_addr   = inet_addr("203.107.54.210");		//使用connect函数接口向服务器发起连接申请int flag_connect = connect(tcp_socket, (struct sockaddr *)&dest_addr, flag_dest);if(flag_connect == -1){fprintf(stderr, "connect socket error,errno:%d,%s\n",errno,strerror(errno));exit(3);}//连接成功后,向服务器发送请求char buf[BUFSIZE] = {0};sprintf(buf, "POST http://v.juhe.cn/laohuangli/d?key=%s&date=%s HTTP/1.1\r\n""HOST: %s\r\n""Content-Type: application/x-www-form-urlencoded\r\n""\r\n",KEY,DATE,HOST);int ret = write(tcp_socket,buf,strlen(buf));if (ret < 0){fprintf(stderr,"send data fail! errno:%d, errmsg:'%s'\n\n",errno, strerror(errno));exit(4);}else{printf("send data success, length:%d byte!\n\n", ret);}//利用select监测套接字状态,当服务器发送数据时,进行接收操作fd_set t_set1;struct timeval tv;//清零集合,并设置超时为五秒钟FD_ZERO(&t_set1);tv.tv_usec = 0;			//微秒为单位tv.tv_sec = 5;			//设置等待时间为五秒// 执行“少量多次”的规则,监测套接字状态while(1){//把套接字加入集合中FD_SET(tcp_socket, &t_set1);int flag_slect = select(tcp_socket + 1, &t_set1, NULL, NULL, &tv);printf("flag_slect = %d\n",flag_slect);//检测集合读状态失败if(flag_slect < 0){close(tcp_socket);//关闭套接字fprintf(stderr,"read data fail! errno:%d, errmsg:'%s'\n\n",errno, strerror(errno));exit(5);}//超时则重新监测if(flag_slect == 0){printf("h:%d sec:%ld usec:%ld\n\n", flag_slect, tv.tv_sec, tv.tv_usec);continue;}//服务器已经发送数据,可以执行读取操作if(flag_slect > 0){memset(buf, 0, BUFSIZE);int i = read(tcp_socket, buf, BUFSIZE);printf("%s\n", buf);if (i == 0){close(tcp_socket);//关闭套接字fprintf(stderr,"read data fail! errno:%d, errmsg:'%s'\n\n",errno, strerror(errno));exit(6);}break;}}//对读取到的数据进行处理,由于响应包体跟响应行+响应字段粘合在一起,所以需要先对获取数据作初步处理char *buf1 = strstr(buf, "{");// 1. 将存储JSON格式的字符串转换成JASON格式数据cJSON *json = cJSON_Parse(buf1);//2. 对转换后的数据进行输出调试char *string = cJSON_Print(json);printf("%s\n", string);//3. 练习:利用cJSON_GetObjectItem获取指定键名的值cJSON *result = cJSON_GetObjectItem(json, "result");cJSON *jishen = cJSON_GetObjectItem(result, "jishen");char *str_jishen = cJSON_Print(jishen);printf("吉神宜趋: %s\n", str_jishen);//关闭套接字close(tcp_socket);return 0;
}

结果展示

image

相关接口指引

  • 一般嵌入式开发中可以使用cJSON库对JSON格式进行解析,cJSON库是基于C语言的一个开源项目,github下载地址:https://github.com/DaveGamble/cJSON
  • 免费API接口工具大全 - 聚合数据 (juhe.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/44238.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式Linux中的LED驱动控制(续)

前面的实例实现了在野火STM32MP157开发板上对三个LED灯的控制,这里来讨论一下该驱动程序的具体实现方式。由于实例使用的是STM32MP157这款芯片,所以先来看一下与该芯片端口操作相关的寄存器。 先看端口模式寄存器MODER,该类型的寄存器在STM32MP157中有11个,即x的值从A到K。…

通讯协议转换Modbus转Profinet网关

Modbus转Profinet网关是工业通信转换设备,能够实现Modbus协议与Profinet协议之间的有效转换和稳定传输。通过该网关,工业设备之间可以实现数据交换和通信,提高生产效率和智能化程度。支持Modbus RTU主从站。此外,Modbus转 Profinet网关自带网络和串口,支持485/232接口Modb…

python栈帧沙箱逃逸

python栈帧沙箱逃逸 一、生成器 生成器(Generator)是 Python 中一种特殊的迭代器,它可以通过简单的函数和表达式来创建。生成器的主要特点是能够逐个产生值,并且在每次生成值后保留当前的状态,以便下次调用时可以继续生成值。这使得生成器非常适合处理大型数据集或需要延迟…

spring-1-IOC、创建bean的方式、创建bean的过程

1.背景 IOC(Inversion of Control,控制反转) 控制反转是一种设计原则,它将对象的创建和管理责任从应用代码中移交给容器。 在Spring中,IOC容器负责管理应用中的所有对象,包括它们的生命周期和相互之间的依赖关系。 IOC的主要目的是为了减少代码之间的耦合,使代码更加模块…

11-CSS定位

CSS定位01 CSS定位概念理解 01 标准流布局概念的理解02 position属性02 相对定位 依然在标准流中 应用场景: 在不影响其它元素的情况下,对当前元素进行微调 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><met…

Combining Recurrent, Convolutional, and Continuous-time Models with Linear State-Space Layers

目录概符号说明LSSL和其它方法的联系代码Gu A., Johnson I., Goel K., Saab K., Dao T., Rudra A., and Re C. Combining recurrent, convolutional, and continuous-time models with linear state-space layers. NeurIPS, 2021.State space representaion-wiki.概 Mamba 系列…

堆基础知识

arenachunk通俗地说,一块由分配器分配的内存块叫做一个 chunk,包含了元数据和用户数据。具体一点,chunk 完整定义如下: struct malloc_chunk {INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk (if free). */INTERNAL_SIZE_T mchunk_size; …

【Azure Spring Apps】Spring App部署上云遇见 502 Bad Gateway nginx

问题描述 在部署Azure Spring App应用后,访问应用,遇见了502 Bad Gateway Nginx。问题解答 502 Bad Gateway, 并且由Nginx返回。而自己的应用中,并没有定义Nginx相关内容,所以需要查看问题是否出现在Azure Spring App服务的设置上。 根据Spring App的通信模型图判断,502的…