Linux_cJSON--数据封装与解析

1. cJSON介绍

  • JSON(JavaScript Object Notation)是一种轻量级的文本数据交换格式, 易于让人阅读. 同时也易于机器解析和生成. JSON虽然是Javascript的一个子集, 但JSON是独立于语言的文本格式, 并且采用了类似C语言的一些习惯.
  • 为什么我们要使用cJSON呢? 我们在传输数据时, 如果只有一个数据比如温度t = 26.53 .我们传输过去一定会知道这个数据是什么. 此时如果数据既有温度和湿度. 那么我们传输过去的是俩个字符串. 此时是不能分辨出温度还是湿度的值.
  • cJSON的使用, 添加序列号, 温度, 湿度, 获取温湿度的时间.
  • cJSON 的格式为:  {
               “sn”: “sds123”,
               “tem”: “12.2”,
               “time”: “13:00”
             }

1.1 cJSON下载(Linux环境下)

  1. cJSON库下载地址:https://github.com/DaveGamble/cJSON
    在这里插入图片描述

  2. 下载到window上, 通过Secure CRT远程登陆我们的虚拟机或者服务器. 使用rz命令将cJSON-master.zip文件添加进去.

  3. 压缩包是 .zip格式 . ubuntu通常已经安装zip, 如果没有zip, 那么安装zip: sudo apt install zip unzip
    解压: unzip cJSON-master.zip

  4. 文件夹内容如下:
    在这里插入图片描述

1.2 cJSON动态库的安装与使用

  1. make all
    在这里插入图片描述
  2. sudo make install
    在这里插入图片描述
  3. $ gcc test.c -lcjson // -l 表示连接时所要的链接库
    在这里插入图片描述
    cjson动态库安装路径为 ‘/usr/local/lib’
    链接器ld提示找不到库文件. ld默认的目录是/lib和/usr/lib, 找不到这个动态库.
    解决方法:
    (1) $ cat /etc/ld.so.conf //如果配置文件中有’/usr/local/lib’, 直接$ sudo ldconfig // 更新配置文件
    ldconfig命令: 主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下.
    (2) 如果没有权限添加路径, 可以export一个全局变量LD_LIBRARY_PATH, 然后运行程序的时候会去这个目录中找共享库.
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib  // 绝对路径!!! 临时生效
    如果想要永久生效, 可以更改配置文件 $ vim ./bashrc
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
    第一种方式使其生效: $ source ~/.bashrc
    第二种方式使其生效: 重新打开终端.
    在这里插入图片描述
    执行’./a.out’ 看到运行结果
    在这里插入图片描述

2. JSON函数的封装

2.1 封装代码及头文件

json格式的封装函数

// json格式的封装函数
int Package_JSON(char *buf, char *str, double tem, char *time)
{
    cJSON   *json;
    char    *ptr = NULL;

    json = cJSON_CreateObject();

    cJSON_AddItemToObject(json, "sn", cJSON_CreateString(str));
    cJSON_AddNumberToObject(json, "tem", tem);
    cJSON_AddStringToObject(json, "time", time);

    ptr = cJSON_Print(json);
    strcpy(buf, ptr);
    free(ptr);
    cJSON_Delete(json);

    return strlen(buf);
}

json格式的解析函数

int Parse_JSON(char *buf, char *sn, double *tem, char *time)
{   
    cJSON   *root;
    cJSON   *temp;
    char    *ptr;
    
    root = cJSON_Parse(buf);
    
    temp = cJSON_GetObjectItem(root, "sn");
    ptr = cJSON_Print(temp);
    strcpy(sn, ptr);
    free(ptr);

    temp = cJSON_GetObjectItem(root, "tem");
    ptr = cJSON_Print(temp);
    *tem = atof(ptr);
    free(ptr);

    temp = cJSON_GetObjectItem(root, "time");
    ptr = cJSON_Print(temp);
    strcpy(time, ptr);
    free(ptr);

    cJSON_Delete(root);

    return 1;
}

Json_Proc.h

#ifndef __JSON_PROC_H__
#define __JSON_PROC_H__
int Package_JSON(char *buf, char *str, double tem, char *time);
int Parse_JSON(char *buf, char *sn, double *tem, char *time);

#endif 

2.2 测试用例

#include "Json_Proc"

int main (int argc, char **argv)
{
    int     rv;
    char    buf[1024];
    char    sn[1024];
    double  temperature;
    char    time[1024];
    
    memset(buf, 0, sizeof(buf));
  	Package_JSON(buf, "sds123", 12.12, "13:00");
    printf("Package_JSON\n%s\n", buf);
    printf("\n");
    
    Parse_JSON(buf, sn, &temperature, time);
    printf("Parse_JSON\n");
    printf("sn:%s\n", sn);
    printf("temperature:%6.2lf\n", temperature);
    printf("time:%s\n", time);
    
    return 0;
} 

2.3 运行结果

在这里插入图片描述

3. socket的应用

  我们在树莓派上获取到温度, 此时如果有一百个树莓派同时发送数据, 那么我们在服务器端接收的数据将不知从那个树莓派发送过来, 客户端将数据以JSON格式进行上传到服务器端, 服务器端将JSON格式的数据进行解析, 获取到产品序列号, 温度, 以及获取温度时间.

3.1 socket 客户端与服务器端代码

客户端代码:

	while(1)
	{
		ds18b20(&temperature);	//  获取树莓派温度
    	rv = Package_JSON(buf, "snab123", temperature, "13:00");
    	printf("buf:%s\n", buf);
    	
		rv=write(sockfd, buf, strlen(buf));  
		if(rv <0)
		{
			printf("Write to server by sockfd[%d] failure: %s\n", sockfd, strerror(errno));
			return -3;
		}

		memset(buf1, 0, sizeof(buf));
		rv=read(sockfd, buf, sizeof(buf));
		if( rv < 0 )
		{
			printf("Read data from server by sockfd[%d] failure: %s\n", sockfd, strerror(errno));
			return -4;
		}
		else if( rv == 0 ) //socket断开
		{
			printf("Socket[%d] get disconnected\n", sockfd);
			return -5;
		}
		else if( rv > 0 )
		{
            printf("success!\n");
			//printf("Read %d bytes data from server: %s\n", rv, buf);
		}
		sleep(10);
	}

服务器端代码

	while(1)
	{
		clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);  //  如果不传NULL, 那么就是cliaddr的大小  
		if(clifd < 0)
		{
			printf("Accept new client failure: %s\n", strerror(errno));
			continue;
		}

		printf("Accept new client[%s:%d] successfully\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
		
		while(1)
		{
			memset(buf, 0, sizeof(buf));
			rv = read(clifd, buf, sizeof(buf));
			if( rv < 0 )
			{
				printf("Read data from clien by sockfd[%d] failure: %s\n", clifd, strerror(errno));
				close(clifd);
				continue;
			}
			else if( rv == 0 )
			{
				printf(" Clifd[%d] get disconnected\n", clifd);
				break;
			}
			else if( rv > 0 )
			{
			    Parse_JSON(buf, sn, &temperature, time);
			    printf("sn:%s\n", sn);
			    printf("temperature:%6.2lf\n", temperature);
			    printf("time:%s\n", time);
			    printf("\n");
			}

			rv = write(clifd, buf, rv);
			if( rv < 0 )
			{
				printf("Write to client by sockfd[%d] failure: %s\n", sockfd, strerror(errno));
				close(clifd);
				continue;
			}
		}
	}

3.2 测试结果

服务器端启动等待客户端连接:
在这里插入图片描述

客户端连接服务器端每十秒发送一次数据
在这里插入图片描述

服务器端解析数据
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值