前言 上一篇分享了:简单认识认识mqtt及mosquitto,但也只是分享了mqtt的一些概念及mosquitto的一些介绍。这不,就有读者来催更了: 这一篇我们就来分享mqtt应用于进程间通信的实例。我们沿用例说嵌入式实用知识之JSON数据这篇文章的综合demo来改造改造。那个综合demo的功能是这样子的: 这是以socket来作为进程间通信的方式,并且这个demo是基于Windows写的,需要包含Windows特定的头文件。 本篇笔记我们把上面这个综合demo改为: 我们用mqtt来作为进程间通信的方式,在Linux下进程测试。 先贴代码:jsonprint进程源码 jsonprint。c:程序功能:组JSON格式数据包并发送(MQTT发布者客户端程序)编译命令:gcccJSON。cjsonprint。cL。。mosquittobuildliblmosquittoojsonprint导出mosquitto动态库:exportLDLIBRARYPATH。。mosquittobuildlib:LDLIBRARYPATH作者:ZhengN公众号:嵌入式大杂烩includestdio。hincludestdlib。hincludestring。hincludecJSON。hinclude。。mosquittolibmosquitto。hdefineSTUNAMELEN32学生结构体typedefstructStudent{charname〔STUNAMELEN〕;名字intnum;学号intcscore;C语言分数}StudentDef,pStudentDef;内部函数声明staticStudentDefStudentDataPrepare(void);staticcharStudentsDataPacket(pStudentDefStu);staticvoidStudentDataSend(constchardata);staticvoidMqttClientInit(void);staticvoidMqttClientClean(void);boolcleansessiontrue;structmosquittomosqNULL;函数:main参数:说明:返回:intmain(void){StudentDefstu{0};charstudataNULL;intstucount0;inti0;MQTT客户端初始化MqttClientInit();需要登记的学生总人数printf(Pleaseinputnumberofstudent:);scanf(d,stucount);while(istucount){准备数据stuStudentDataPrepare();JSON格式数据组包studataStudentsDataPacket(stu);发送数据StudentDataSend(studata);}回收操作MqttClientClean();return0;}函数:StudentDataPrepare,准备组包需要的数据参数:说明:返回:获取得到的数据staticStudentDefStudentDataPrepare(void){charname〔STUNAMELEN〕{0};intnum0;intcscore0;StudentDefstu;名字printf(Pleaseinputname:);scanf(s,name);if(strlen(name)STUNAMELEN){strncpy((char)stu。name,name,strlen(name)1);}else{printf(Thenameistoolong);}学号printf(Pleaseinputnum(0100):);scanf(d,num);stu。numnum;C语言分数printf(Pleaseinputcscore(0100):);scanf(d,cscore);stu。cscorecscore;returnstu;}函数:StudentsDataPacket,JSON格式数据组包参数:Stu:组studentjson数据包需要的数据说明:返回:JSON格式的字符串staticcharStudentsDataPacket(pStudentDefStu){charresstringNULL;返回值cJSONnameNULL;名字cJSONnumNULL;学号cJSONcscoreNULL;C语言分数创建一个JSON对象,{}扩起来cJSONobjcJSONCreateObject();if(objNULL){gotoend;}创建name:xxx键值对namecJSONCreateString(Stuname);if(nameNULL){gotoend;}cJSONAddItemToObject(obj,name,name);创建num:207键值对numcJSONCreateNumber(Stunum);if(nameNULL){gotoend;}cJSONAddItemToObject(obj,num,num);创建cscore:95键值对cscorecJSONCreateNumber(Stucscore);if(nameNULL){gotoend;}cJSONAddItemToObject(obj,cscore,cscore);resstringcJSONPrint(obj);呈现为JSON格式resstringcJSONPrintUnformatted(obj);呈现为无格式if(resstringNULL){fprintf(stderr,Failedtoprintmonitor。);}异常情况统一Delete(free)end:cJSONDelete(obj);returnresstring;}函数:StudentDataSend,JSON格式字符串数据组包发送参数:data:要发送的数据说明:返回:JSON格式的字符串staticvoidStudentDataSend(constchardata){printf(s:s,FUNCTION,data);发布消息mosquittopublish(mosq,NULL,testtopic,strlen(data)1,(constchar)data,0,0);}函数:MqttClientInit,MQTT客户端初始化参数:void说明:返回:staticvoidMqttClientInit(void){libmosquitto库初始化mosquittolibinit();创建mosquitto客户端mosqmosquittonew(NULL,cleansession,NULL);if(NULLmosq){printf(Createmqttclientfailed。。。);mosquittolibcleanup();return;}连接服务器if(mosquittoconnect(mosq,localhost,1883,60)){printf(Unabletoconnect。。。);return;}网络消息处理线程intloopmosquittoloopstart(mosq);if(loop!MOSQERRSUCCESS){printf(mosquittolooperror);return;}}函数:MqttClientClean,MQTT客户端清理操作参数:void说明:返回:staticvoidMqttClientClean(void){mosquittodestroy(mosq);mosquittolibcleanup();}jsonparse进程源码 jsonparse。c:程序功能:接收JSON数据并解析(MQTT订阅者客户端程序)编译命令:gcccJSON。cjsonparse。cL。。mosquittobuildliblmosquittoojsonparse导出mosquitto动态库:exportLDLIBRARYPATH。。mosquittobuildlib:LDLIBRARYPATH作者:ZhengN公众号:嵌入式大杂烩includestdio。hincludestdlib。hincludestring。hincludecJSON。hinclude。。mosquittolibmosquitto。hdefineSTUNAMELEN32学生结构体typedefstructStudent{charname〔STUNAMELEN〕;名字intnum;学号intcscore;C语言分数}StudentDef,pStudentDef;内部函数声明staticvoidStudentsDataParse(pStudentDefStu,constcharJsonStudnetData);staticvoidPrintParseResult(constpStudentDefStu);staticvoidSaveParseResult(constpStudentDefStu);staticvoidmymessagecallback(structmosquittomosq,voiduserdata,conststructmosquittomessagemessage);staticvoidmyconnectcallback(structmosquittomosq,voiduserdata,intresult);内部全局变量staticFILEstufpNULL;函数:main参数:说明:返回:boolcleansessiontrue;intmain(void){structmosquittomosqNULL;libmosquitto库初始化mosquittolibinit();创建mosquitto客户端mosqmosquittonew(NULL,cleansession,NULL);if(NULLmosq){printf(Createmqttclientfailed。。。);mosquittolibcleanup();return1;}绑定连接、消息接收回调函数mosquittoconnectcallbackset(mosq,myconnectcallback);mosquittomessagecallbackset(mosq,mymessagecallback);连接服务器if(mosquittoconnect(mosq,localhost,1883,60)){printf(Unabletoconnect。。。);return1;}循环处理网络消息mosquittoloopforever(mosq,1,1);回收操作mosquittodestroy(mosq);mosquittolibcleanup();return0;}函数:StudentsDataParse,JOSN格式学生期末数据解析参数:JsonStudnetData:JSON数据Stu:保存解析出的有用数据说明:返回:staticvoidStudentsDataParse(pStudentDefStu,constcharJsonStudnetData){cJSONstudentjsonNULL;studentjson操作对象,可代表{}扩起来的内容cJSONnameNULL;cJSONnumNULL;cJSONcscoreNULL;开始解析studentjsoncJSONParse(JsonStudnetData);if(NULLstudentjson){constcharerrorptrcJSONGetErrorPtr();if(errorptr!NULL){fprintf(stderr,Errorbefore:s,errorptr);}gotoend;}解析获取name得值namecJSONGetObjectItemCaseSensitive(studentjson,name);if(cJSONIsString(name)(namevaluestring!NULL)){memset(Stuname,0,STUNAMELENsizeof(char));memcpy(Stuname,namevaluestring,strlen(namevaluestring));}解析获取num的值numcJSONGetObjectItemCaseSensitive(studentjson,num);if(cJSONIsNumber(num)){Stunumnumvalueint;}解析获取cscore的值cscorecJSONGetObjectItemCaseSensitive(studentjson,cscore);if(cJSONIsNumber(cscore)){Stucscorecscorevalueint;}end:cJSONDelete(studentjson);}函数:PrintParseResult,打印输出解析结果参数:说明:返回:staticvoidPrintParseResult(constpStudentDefStu){printf(name:s,num:d,cscore:d,Stuname,Stunum,Stucscore);}函数:SaveParseResult,保存解析结果参数:Stu:需要保存的数据说明:返回:staticvoidSaveParseResult(constpStudentDefStu){charwritebuf〔512〕{0};staticintstucount0;以可在文件末尾追加内容的方式打开文件if((stufpfopen(ParseResult。txt,a))NULL){printf(Openfileerror!);returnexit(EXITFAILURE);}按指定格式写入文件snprintf(writebuf,512,name:s,num:d,cscore:d,Stuname,Stunum,Stucscore);sizetlenfwrite((char)writebuf,1,strlen(writebuf),stufp);文件位置指针偏移fseek(stufp,lenstucount,SEEKSET);stucount;关闭文件fclose(stufp);}函数:mymessagecallback,消息接收回调函数参数:返回:staticvoidmymessagecallback(structmosquittomosq,voiduserdata,conststructmosquittomessagemessage){StudentDefstu{0};if(messagepayloadlen){printf(ss,messagetopic,(char)messagepayload);解析JSON数据StudentsDataParse(stu,(constchar)messagepayload);打印输出解析结果PrintParseResult(stu);保存数据到文件SaveParseResult(stu);}else{printf(s(null),messagetopic);}fflush(stdout);}函数:myconnectcallback,连接回调函数参数:返回:staticvoidmyconnectcallback(structmosquittomosq,voiduserdata,intresult){if(!result){订阅testtopic主题的消息mosquittosubscribe(mosq,NULL,testtopic,0);}else{fprintf(stderr,Connectfailed);}}编译运行 1、编译生成jsonparse、jsonprint程序:gcccJSON。cjsonparse。cL。。mosquittobuildliblmosquittoojsonparsegcccJSON。cjsonprint。cL。。mosquittobuildliblmosquittoojsonprint 这里用到链接动态库的方式生成可执行程序。关于动态链接与静态链接,可查看往期笔记:静态链接与动态链接(Linux)、静态链接与动态链接。 2、执行jsonparse、jsonprint程序: 执行这两个程序会报错: 。jsonparse:errorwhileloadingsharedlibraries:libmosquitto。so。1:cannotopensharedobjectfile:Nosuchfileordirectoryjsonprint:errorwhileloadingsharedlibraries:libmosquitto。so。1:cannotopensharedobjectfile:Nosuchfileordirectory 这是因为不能找到共享库文件libmosquitto。so。1,加载失败。 因为一般情况下Linux会在usrlib路径中搜索需要用到的库,而libmosquitto。so。1库并不在这个路径下。 解决方法有两种:一种就是把这个文件拷贝至usrlib路径下,但是一般不允许这样做,一般用户也不允许往这个路径里拷贝东西。另一种就是把libmosquitto。so。1库所在路径增加为动态库的搜索路径,命令为:exportLDLIBRARYPATH。。mosquittobuildlib:LDLIBRARYPATH 关于这方面的说明可以阅读往期笔记:静态链接与动态链接(Linux) 按照上述方法添加动态库搜索路径之后就可以正常运行这两个程序: ParseResult。txt文本里得到: 实验成功! 以上就是本次的分享,代码写得比较仓促,如有错误,麻烦指出,谢谢!由于准备demo花了挺多时间,包括注释也写了很多。所以本篇文章就不做过多的说明,感兴趣的朋友可以结合本篇文章的demo及mosquittoclientpubclient。c、mosquittoclientsubclient。c这两个源文件。 本篇文章的demo: 由于篇幅有限。代码可在私信回复关键词:jsonmqttdemo,即可获取。 1024G嵌入式资源大放送!包括但不限于CC、单片机、Linux等。私信回复1024,即可免费获取!