Linux高并发网络编程开发——xml json

在学习Linux高并发网络编程开发总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

10-Linux系统编程-第16天(xml json)

目录:
一、学习目标
二、libevent复习
1、libevent整体工作流程回顾
2、libevent  socket服务器复习
3、libevent socket客户端代码实现
4、bug
三、xml
1、xml文件格式
2、xml示例文件
3、xml文件的设计
4、mxml安装和配置
5、mxml生成文件函数介绍
6、使用mxml api生成xml文件
7、mxml获取文件数据
8、mxml格式文件解析
四、json
1、json文件格式
2、json格式示例文件
3、cjson介绍
4、cjson api创建json文件
5、cjson解析api
》附:QT中的json类

 

一、学习目标

xml

- xml基础语法和规范

- C程序如何使用xml开源库

- 借助开源库,在C程序中生成xml文件

- 已知一个xml文件,如何借助开源库解析xml文件数据

json

- json的基础语法和规范

- C程序中如何使用json开源库-cjson

- 使用cjson生成json文件

- 已知一个json文件,使用cjson库解析文件数据

 

二、libevent复习

1、libevent整体工作流程回顾

2、libevent  socket服务器复习

3、libevent socket客户端代码实现

>touch client.c

>vi client.c

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <sys/types.h>
  5 #include <sys/stat.h>
  6 #include <string.h>
  7 #include <event2/event.h>
  8 #include <event2/bufferevent.h>
  9 #include <arpa/inet.h>
 10 
 11 // 读回调
 12 void read_cb(struct bufferevent *bev, void *arg)
 13 {
 14     // 接收对方发送过来的数据
 15     char buf[1024] = {0}; 
 16     int len = bufferevent_read(bev, buf, sizeof(buf));
 17     printf("recv data: %s\n", buf);
 18     
 19     // 给对方发数据
 20     bufferevent_write(bev, buf, len+1);
 21     printf("数据已经发送完成...\n");
 22 }
 23 
 24 // 写回调
 25 void write_cb(struct bufferevent *bev, void *arg)
 26 {
 27     printf("我是一个没有什么卵用的函数....\n");
 28 }
 29 
 30 // 事件回调
 31 void event_cb(struct bufferevent *bev, short events, void *arg)
 32 {
 33     if (events & BEV_EVENT_EOF)
 34     {
 35         printf("connection closed\n");  
 36     }
 37     else if(events & BEV_EVENT_ERROR)   
 38     {
 39         printf("some other error\n");
 40     }
 41     else if(events & BEV_EVENT_CONNECTED)
 42     {
 43         printf("成功连接到服务器, O(∩_∩)O哈哈~\n");
 44         return;
 45     }
 46     
 47     // 释放资源
 48     bufferevent_free(bev);
 49     printf("free bufferevent...\n");
 50 }
 51 
 52 // 终端接受输入,将数据发给server
 53 void read_terminal(evutil_socket_t fd, short what, void *arg)
 54 {
 55     // 读终端中的数据
 56     char buf[1024] = {0}; 
 57     int len = read(fd, buf, sizeof(buf));
 58     
 59     // 将数据发送给server
 60     struct bufferevent* bev = (struct bufferevent*)arg;
 61     printf("请输入要发送的数据: \n");
 62     bufferevent_write(bev, buf, len+1);
 63 }
 64 
 65 
 66 int main(int argc, const char* argv[])
 67 {
 68     // init server info
 69     struct sockaddr_in serv;
 70     memset(&serv, 0, sizeof(serv));
 71     serv.sin_family = AF_INET;
 72     serv.sin_port = htons(9876);
 73     evutil_inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
 74     
 75     //创建事件处理框架
 76     struct event_base* base;
 77     base = event_base_new();
 78     
 79     //创建事件
 80     // 连接服务器 -- fd 
 81     int fd = socket(AF_INET, SOCK_STREAM, 0);
 82     //fd - bufferevent
 83     struct bufferevent* bev;
 84     bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
 85 
 86     // 连接服务器
 87     bufferevent_socket_connect(bev, (struct sockaddr*)&serv, sizeof(serv));
 88 
 89     // 给缓冲区设置回调
 90     bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
 91     bufferevent_enable(bev, EV_READ | EV_PERSIST);
 92 
 93     // 接收键盘输入
 94     // 创建一个事件
 95     struct event* ev = event_new(base, STDIN_FILENO, 
 96                                  EV_READ | EV_PERSIST, 
 97                                  read_terminal, bev);
 98     //添加事件到event_base
 99     event_add(ev, NULL);
100     
101     //启动事件循环
102     event_base_dispatch(base);
103     
104     //释放资源
105     event_base_free(base);
106 
107     return 0;
108 }

>gcc client.c -o client -levent

>./server

(打开另一个终端,先把之前的客户端拷贝至bufferevent目录下,然后编译后运行./client 127.0.0.1 9876;然后发送数据,查看原server终端的接收情况)

》报错:客户端无限写?

 

4、bug

》原因及解决:读回调中read_cb给终端发送数据bufferevent_write去掉,因为终端接受输入,将数据发给server的read_terminal已经发送了数据。所以将read_cb函数中bufferevent_write(bev, buf, len+1);注释掉。

 

三、xml

1、xml文件格式

>test.xml

 1 <!-- 注释 -->
 2 <!-- 文件头 -->
 3 <?xml version="1.0" encoding="utf-8"?>
 4 <!-- 树状结构的标签 -->
 5 <!-- 根标签 -- 自个起名  只有一个 -->
 6 <!-- 便签的值区分大小写 -->
 7 
 8 
 9 <!-- 标签一般成对出现 -->
10 <Zhangsan>
11     <!-- 不成对-->
12     <lisi/>
13     <!-- 子标签 -->
14     <child>
15         <!-- 没有子标签,标签必须有值 -->
16         <!-- 标签设置属性 report:属性,属性值需要使用""包含 -->
17         <name report = "yes">zhang1</name>
18         <age month="1">12</age>
19         <sex></sex>
20     </child>
21     <!-- 子标签 -->
22     <child>
23         <name>zhang2</name>
24         <age>4</age>
25         <sex></sex>
26     </child>
27 </Zhangsan>

 

2、xml示例文件

>car.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <car>
 3     <factory name="一汽大众">
 4         <brand>
 5             <name>高尔夫</name>
 6             <color>红色</color>
 7             <price>15万</price>
 8         </brand>
 9         <brand>
10             <name>速腾</name>
11             <color>银白</color>
12             <price>18万</price>
13         </brand>
14         <brand>
15             <name>迈腾</name>
16             <color>黑灰</color>
17             <price>28万</price>
18         </brand>
19     </factory>
20     <factory name="上海大众">
21         <brand>
22             <name>帕萨特</name>
23             <color>黑色</color>
24             <price>25万</price>
25         </brand>
26         <brand>
27             <name>POLO</name>
28             <color>灰色</color>
29             <price>8万</price>
30         </brand>
31     </factory>
32 </car>

 

3、xml文件的设计

>china.xml(改为石家庄)

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <China>
 3     <City>
 4         <Name isbig="true">北京</Name>
 5         <Area>1.641万平方千米</Area>
 6         <Population>2200万</Population>
 7     </City>
 8     <City>
 9         <Name isbig="false">石家庄</Name>
10         <Area>15848平方千米</Area>
11         <Population>107万</Population>
12     </City>
13 </China>

 

4、mxml安装和配置

》源码安装——安装文件:mxml-2.10.tar

>tar xvf mxml-2.10.tar

>cd msml-2.10

>ls

>vi README

>./configure

>make

>sudo make install

》测试是否安装成功

>ls (查看是否有testmxml.c)

>gcc testmxml.c -lmxml -lpthread -o testmxml

>./testmxml test.xml

(查看test.xml文件是否原样输出)

》问题:编译为什么需要加-lpthread?

答:安装时实现需要用到线程库,可以避免,安装时采用./configure --enable-threads=no

》./configure --enable-threads=no && make 是什么意思?

答:一句话两个命令,第一条执行成功,执行第二条

 

5、mxml生成文件函数介绍

》开源库minixml的使用:

 

6、使用mxml api生成xml文件

>touch create_xml.c

>vi create_xml.c

 1 #include <stdio.h>
 2 #include <mxml.h>
 3 
 4 int main(int argc, const char* argv[])
 5 {
 6     // 创建xml文件头节点
 7     mxml_node_t *xml = mxmlNewXML("1.0");
 8 
 9     // 创建xml根节点 - china
10     mxml_node_t* china = mxmlNewElement(xml, "China");
11 
12 
13     // 创建城市节点
14     mxml_node_t* city = mxmlNewElement(china, "City");
15     // 添加子节点
16     // name
17     mxml_node_t* name = mxmlNewElement(city, "Name");
18     // 设置标签值
19     mxmlNewText(name, 0, "北京");
20     mxmlElementSetAttr(name, "isbig", "true");
21     // 面积
22     mxml_node_t* area = mxmlNewElement(city, "Area");
23     mxmlNewText(area, 0, "1.641万平方千米");
24     // 人口
25     mxml_node_t* popu = mxmlNewElement(city, "Population");
26     mxmlNewText(popu, 0, "2200万");
27 
28     // 第二个城市节点
29     city = mxmlNewElement(china, "City");
30     // name
31     name = mxmlNewElement(city, "Name");
32     mxmlNewText(name, 0, "石家庄");
33     mxmlElementSetAttr(name, "isbig", "false");
34     area = mxmlNewElement(city, "Area");
35     mxmlNewText(area, 0, "15848平方千米");
36     popu = mxmlNewElement(city, "Population");
37     mxmlNewText(popu, 0, "107万");
38 
39     // 将xml内容保存到磁盘
40     FILE* fp = fopen("china.xml", "w");
41     mxmlSaveFile(xml, fp, MXML_NO_CALLBACK);
42     fclose(fp);
43     mxmlDelete(xml);
44     
45     return 0;
46 }

>gcc create_xml.c -lmxml -lpthread -o create

>./create

>cat china.xml

问题:创建的China.xml文件的格式默认写在一行,看着非常不直观?

答:可以使用XMLView.exe看,将china.xml拖拽进去后即可。另外XMLView.exe还有“容错”功能,勾选“Options”->“Strict XML parsing”可以自动识别错误并改正。

 

7、mxml获取文件数据

  

 

8、mxml格式文件解析

》练习解析car.xml

》文件准备—car.xml,car2.xml

>car.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <car>
 3     <factory name="一汽大众">
 4         <brand>
 5             <name>高尔夫</name>
 6             <color>红色</color>
 7             <price>15万</price>
 8         </brand>
 9         <brand>
10             <name>速腾</name>
11             <color>银白</color>
12             <price>18万</price>
13         </brand>
14         <brand>
15             <name>迈腾</name>
16             <color>黑灰</color>
17             <price>28万</price>
18         </brand>
19     </factory>
20     <factory name="上海大众">
21         <brand>
22             <name>帕萨特</name>
23             <color>黑色</color>
24             <price>25万</price>
25         </brand>
26         <brand>
27             <name>POLO</name>
28             <color>灰色</color>
29             <price>8万</price>
30         </brand>
31     </factory>
32 </car>

>car2.xml

1 <?xml version="1.0" encoding="utf-8"?><car><factory name="一汽大众"><brand><name>高尔夫</name><color>红色</color><price>15万</price></brand><brand><name>速腾</name><color>银白</color><price>18万</price></brand><brand><name>迈腾</name><color>黑灰</color><price>28万</price></brand></factory><factory name="上海大众"><brand><name>帕萨特</name><color>黑色</color><price>25万</price></brand><brand><name>POLO</name><color>灰色</color><price>8万</price></brand></factory></car>

》练习—解析car.xml:

>touch parsecar.c

>vi parsecar.c

 1 #include <stdio.h>
 2 #include "mxml.h"
 3 
 4 int main(int argc, const char* argv[])
 5 {
 6     if(argc < 2)
 7     {
 8         printf("./a.out filename\n");
 9         return 0;
10     }
11     // 加载xml文件
12     FILE* fp = fopen(argv[1], "r");
13     mxml_node_t* root = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
14 
15     // 找到第一个factory节点
16     mxml_node_t* factory = mxmlFindElement(root, root, "factory", "name", NULL, MXML_DESCEND);
17     // 循环查找
18     while( factory  )
19     {
20         // 打印几点的属性值
21         printf("factory attr: %s\n", mxmlElementGetAttr(factory, "name"));
22 
23         // 向下移动一个节点
24         mxml_node_t* brand = mxmlWalkNext(factory, root, MXML_DESCEND);
25         while( brand )
26         {
27             // name
28             mxml_node_t* node = mxmlWalkNext(brand, root, MXML_DESCEND_FIRST);
29             printf("    name: %s\n", mxmlGetText(node, 0));
30             // color
31             node = mxmlWalkNext(node, root, MXML_NO_DESCEND);
32             printf("    color: %s\n", mxmlGetText(node, 0));
33             // price
34             node = mxmlWalkNext(node, root, MXML_NO_DESCEND);
35             printf("    price: %s\n", mxmlGetText(node, 0));
36             printf("    =========================================\n");
37 
38             // 找到下一个品牌节点
39             brand = mxmlFindElement(brand, root, "brand", NULL, NULL, MXML_NO_DESCEND);
40         }
41         // 打印该厂家对应的车辆品牌和属性信息
42         // 查找下一个节点
43         factory = mxmlFindElement(factory, root, "factory", "name", NULL, MXML_NO_DESCEND);
44     }
45     mxmlDelete(root);
46     fclose(fp);
47 
48     return 0;
49 }

>gcc parsecar.c -lmxml -o parse

>./parse car.xml

问题:(./parse car.xml)解析错误,名字对不上?而./parse car2.xml)解析正确?

答:函数mxmlWalkNext有bug,有换行会出问题,慎用!!!最好选用mxmlFindElement。

 

四、json

1、json文件格式

》注意:

1)不论是json对象还是json数组,json格式的文件中对象或数组最后一个元素后都没有逗号 !

2)json根对象或json根数组只能有一个。

 

2、json格式示例文件

>login.json

1 {
2     "KSF": "康师傅",
3     "Kevin": "Apple",
4     "Leilei": "loveHanMeiMei",
5     "Licy": "red",
6     "Lucy": "HelloWorld"
7 }

>brand.json

 1 {
 2     "奔驰": {
 3         "factory": "一汽大众",
 4         "last": 31,
 5         "price": 83,
 6         "sell": 49,
 7         "sum": 80,
 8     },
 9     "奥迪A6": {
10         "factory": "一汽大众",
11         "last": 15,
12         "price": 36,
13         "sell": 35,
14         "sum": 50
15     },
16     "宝来": {
17         "factory": "一汽大众",
18         "last": 75,
19         "price": 41,
20         "sell": 5,
21         "sum": 80
22     },
23     "富康": {
24         "factory": "二汽神龙",
25         "last": 38,
26         "price": 28,
27         "sell": 22,
28         "sum": 60
29     },
30     "帕萨特": {
31         "factory": "上海大众",
32         "last": 42,
33         "price": 27,
34         "sell": 23,
35         "sum": 65
36     },
37     "捷达": {
38         "factory": "一汽大众",
39         "last": 69,
40         "price": 10,
41         "sell": 11,
42         "sum": 80
43     },
44     "标致307": {
45         "factory": "二汽神龙",
46         "last": 58,
47         "price": 27,
48         "sell": 12,
49         "sum": 70
50     },
51     "桑塔纳": {
52         "factory": "上海大众",
53         "last": 63,
54         "price": 25,
55         "sell": 12,
56         "sum": 75
57     },
58     "毕加索": {
59         "factory": "二汽神龙",
60         "last": 29,
61         "price": 39,
62         "sell": 21,
63         "sum": 50
64     }
65 }

>saleList.json

 1 {
 2     "2016-07-18": {
 3         "02:17:51": {
 4             "brand": "奔驰",
 5             "factory": "一汽大众",
 6             "number": 1,
 7             "sum": 83
 8         },
 9         "02:17:54": {
10             "brand": "奔驰",
11             "factory": "一汽大众",
12             "number": 1,
13             "sum": 83
14         },
15         "02:17:59": {
16             "brand": "富康",
17             "factory": "二汽神龙",
18             "number": 2,
19             "sum": 56
20         },
21         "02:22:37": {
22             "brand": "奔驰",
23             "factory": "一汽大众",
24             "number": 1,
25             "sum": 83
26         },
27         "02:22:40": {
28             "brand": "奔驰",
29             "factory": "一汽大众",
30             "number": 1,
31             "sum": 83
32         },
33         "09:08:36": {
34             "brand": "富康",
35             "factory": "二汽神龙",
36             "number": 2,
37             "sum": 56
38         },
39         "09:17:22": {
40             "brand": "奔驰",
41             "factory": "一汽大众",
42             "number": 3,
43             "sum": 249
44         }
45     },
46     "2016-07-19": {
47         "09:27:24": {
48             "brand": "富康",
49             "factory": "二汽神龙",
50             "number": 1,
51             "sum": 28
52         },
53         "11:05:17": {
54             "brand": "标致307",
55             "factory": "二汽神龙",
56             "number": 2,
57             "sum": 54
58         }
59     },
60     "2016-09-25": {
61         "10:07:24": {
62             "brand": "帕萨特",
63             "factory": "上海大众",
64             "number": 9,
65             "sum": 243
66         },
67         "10:07:34": {
68             "brand": "宝来",
69             "factory": "一汽大众",
70             "number": 3,
71             "sum": 123
72         }
73     },
74     "2016-10-07": {
75         "16:48:35": {
76             "brand": "奔驰",
77             "factory": "一汽大众",
78             "number": 2,
79             "sum": 166
80         }
81     }
82 }

>car.json

 1 {
 2     "奔驰":    {
 3         "factory":    "一汽大众",
 4         "last":    31,
 5         "price":    83,
 6         "sell":    49,
 7         "sum":    80,
 8         "other":    [123, true, "hello, world", {
 9                 "梅赛德斯奔驰":    "心所向, 持以恒"
10             }]
11     }
12 }

 

3、cjson介绍

》安装——安装文件:cJSON-master.zip

>mkdir ToolKit (cJSON-master.zipk拷贝至此文件)

>unzip cJSON-master.zip

>cd cJSON-master

>vi README.md

>ls

使用:直接把cJSON.h和JSON.c拷贝到要使用的目录下即可,然后编译gcc xxx.c cJSON.c -o xxx。

》cjson api:

   

 

4、cjson api创建json文件

先把cJSON.h和JSON.c拷贝到要使用的目录下。

》准备创建的文件为:car.json

 1 {
 2     "奔驰":    {
 3         "factory":    "一汽大众",
 4         "last":    31,
 5         "price":    83,
 6         "sell":    49,
 7         "sum":    80,
 8         "other":    [123, true, "hello, world", {
 9                 "梅赛德斯奔驰":    "心所向, 持以恒"
10             }]
11     }
12 }

》创建如下:

>touch Json_create.c

>vi Json_create.c

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <string.h>
 7 #include "cJSON.h"
 8 
 9 int main(int argc, const char* argv[])
10 {
11     // 创建对象
12     cJSON* obj = cJSON_CreateObject();
13 
14     // 创建子对象
15     cJSON* subObj = cJSON_CreateObject();
16     // 添加key-value
17     cJSON_AddItemToObject(subObj, "factory", cJSON_CreateString("一汽大众"));
18     cJSON_AddItemToObject(subObj, "last", cJSON_CreateNumber(31));
19     cJSON_AddItemToObject(subObj, "price", cJSON_CreateNumber(83));
20     cJSON_AddItemToObject(subObj, "sell", cJSON_CreateNumber(49));
21     cJSON_AddItemToObject(subObj, "sum", cJSON_CreateNumber(80));
22 
23     // 创建json数组
24     cJSON* array = cJSON_CreateArray();
25     // array添加元素
26     cJSON_AddItemToArray(array, cJSON_CreateNumber(124));
27     cJSON_AddItemToArray(array, cJSON_CreateBool(1));
28     cJSON_AddItemToArray(array, cJSON_CreateString("hello, world"));
29 
30     // 数组中的对象
31     cJSON* subsub = cJSON_CreateObject();
32     cJSON_AddItemToObject(subsub, "梅赛德斯奔驰", 
33                           cJSON_CreateString("心所向, 持以恒"));
34     cJSON_AddItemToArray(array, subsub);
35 
36     cJSON_AddItemToObject(subObj, "other", array);
37 
38     // obj中添加key - value
39     cJSON_AddItemToObject(obj, "奔驰", subObj);
40 
41     // 数据格式化
42     char* data = cJSON_Print(obj);
43     FILE* fp = fopen("car.json", "w");
44     fwrite(data, sizeof(char), strlen(data)+1, fp);
45     fclose(fp);
46 
47     return 0;
48 }

>gcc Json_create.c cJSON.c -o create

》报错截图如下:

分析:floor向下取整,使用了数学库math,所以编译时加入-lm

>gcc Json_create.c cJSON.c -o create -lm

>./create

>cat car.json

 

5、cjson解析api

》cjson解析json文件:

    

》解析出来后如何把cJSON类型转换为相应的属性?

查看cJSON.h:

》练习—解析car.json:

》文件准备:car.json

>car.json

 1 {
 2     "奔驰":    {
 3         "factory":    "一汽大众",
 4         "last":    31,
 5         "price":    83,
 6         "sell":    49,
 7         "sum":    80,
 8         "other":    [123, true, "hello, world", {
 9                 "梅赛德斯奔驰":    "心所向, 持以恒"
10             }]
11     }
12 }

>touch parsecar.c

>vi parsecar.c

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include "cJSON.h"
 4 
 5 int main(int argc, const char* argv[])
 6 {
 7     if(argc < 2)
 8     {
 9         printf("./a.out jsonfile\n");
10         return 0;
11     }
12 
13     // 加载json文件 
14     FILE* fp = fopen(argv[1], "r");
15     char buf[1024] = {0};
16     fread(buf, 1, sizeof(buf), fp);
17     cJSON* root = cJSON_Parse(buf);
18 
19     cJSON* subobj = cJSON_GetObjectItem(root, "奔驰");
20     // 判断对象是否存在
21     if( subobj )
22     {
23         // 获取子对象
24         cJSON* factory = cJSON_GetObjectItem(subobj, "factory");
25         cJSON* last = cJSON_GetObjectItem(subobj, "last");
26         cJSON* price = cJSON_GetObjectItem(subobj, "price");
27         cJSON* sell = cJSON_GetObjectItem(subobj, "sell");
28         cJSON* sum = cJSON_GetObjectItem(subobj, "sum");
29         cJSON* other = cJSON_GetObjectItem(subobj, "other");
30 
31         // 打印value值  另一种方式:cJSON_Print可以把cJSON*强制转为字符串
32         printf("奔驰:\n");
33         printf("    factory: %s\n", cJSON_Print(factory));
34         printf("    last: %s\n", cJSON_Print(last));
35         printf("    price: %s\n", cJSON_Print(price));
36         printf("    sell: %s\n", cJSON_Print(sell));
37         printf("    sum: %s\n", cJSON_Print(sum));
38 
39         // 打印数组内容
40         printf("    other:\n");
41         if(other->type == cJSON_Array)
42         {
43             for(int i=0; i<cJSON_GetArraySize(other); ++i)
44             {
45                 cJSON* node = cJSON_GetArrayItem(other, i);
46                 // 判断数据类型
47                 if(node->type == cJSON_String)
48                 {
49                     printf("        %s  \n", node->valuestring);
50                 }
51                 if(node->type == cJSON_Number)
52                 {
53                     printf("        %d\n", node->valueint);
54                 }
55                 if(node->type == cJSON_True)
56                 {
57                     printf("        %d\n", node->valueint);//node无bool类型
58                 }
59                 if(node->type == cJSON_False)
60                 {
61                     printf("        %d\n", node->valueint);
62                 }
63             }
64         }
65     }
66 
67     cJSON_Delete(root);
68     fclose(fp);
69 
70 
71     return 0;
72 }

>gcc parsecar.c cJSON.c -o parse -lm

>./parse car.json

 

》附:QT中的json类

 

 

在学习Linux高并发网络编程开发总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

posted on 2020-07-13 09:34  Alliswell_WP  阅读(243)  评论(0编辑  收藏  举报

导航