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环境下)
-
cJSON库下载地址:https://github.com/DaveGamble/cJSON
-
下载到window上, 通过Secure CRT远程登陆我们的虚拟机或者服务器. 使用rz命令将cJSON-master.zip文件添加进去.
-
压缩包是 .zip格式 . ubuntu通常已经安装zip, 如果没有zip, 那么安装zip: sudo apt install zip unzip
解压: unzip cJSON-master.zip -
文件夹内容如下:
1.2 cJSON动态库的安装与使用
- make all
- sudo make install
- $ 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 测试结果
服务器端启动等待客户端连接:
客户端连接服务器端每十秒发送一次数据
服务器端解析数据