14

Linux Socket 收发Json

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUxMTk4MzY3MA%3D%3D&%3Bmid=2247484541&%3Bidx=1&%3Bsn=7e331fb133c8cef37f555638fcd3adf9
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,麻烦点个在看或点个赞,感谢~

不管是Qt开发还是 linux 嵌入式应用开发,一个人的核心竞争力还是不断思考,也就是不断琢磨。

下面的程序主要是Linux C Socket 读取 JSON 文件并传输,然后再写入文件,其中使用了 cJSON 库,关于 cJSON 库不过多介绍,主要介绍整体的思路。

1. Server 端

使用的是socket 阻塞式,没有使用 selectpollepoll

接收端按照JSON格式解析数据,并提取感兴趣 Key 所对应的 Value

程序功能挺快就可以做好,做完之后进行拆解,将socket通信独立出来, JSON 解析、写文件、响应客户端 JSON 数据等分别写成函数。

对函数入参的判断、文件操作等的成功与否的判断;程序实际功能代码并不是很多,但是参数检查、结果判断等也占了一些空间

Main函数调用:

#include "socketServer.h"


#include <stdio.h>


int main()

{

int socketServerFd = -1;

socketServerFd = SocketServer_Init("127.0.0.1", 9999);

if(-1 == socketServerFd)

{

printf("create socket server fd faild \n");

}


RecDataFromClient(socketServerFd);


return 0;

}

函数封装:

int ParseRecvJsonData(const char * recvdata, int *outLogLevel);

int WriteLogLevelToFileJson(const char *filePathName, int logLevel);

int CreateRespondInfoJson(char *respondInfoJson, const char* recvJsonData,const int writeFileRet);


int SocketServer_Init(const char *ip, int port);

int RecDataFromClient(int serverFd);

一些具体实现:

int ParseRecvJsonData(const char * recvdata, int *outLogLevel)

{

int nRet = -1;

*outLogLevel = -1;


if(NULL == recvdata)

{

return -1;

}


cJSON *parseRoot = NULL;

cJSON *levelItem = NULL;


parseRoot = cJSON_Parse(recvdata);


if (parseRoot)

{

levelItem = cJSON_GetObjectItem(parseRoot, "level");

if (levelItem)

{

*outLogLevel = levelItem->valueint;

nRet = 0;

}

else

{

nRet = -1;

goto end;

}


}

else

{

nRet = -1;

goto end;

}


end:

if (parseRoot)

{

cJSON_Delete(parseRoot);

parseRoot = NULL;

}

return nRet;

}


int WriteLogLevelToFileJson(const char *filePathName, int logLevel)

{

int nRet = 0;

cJSON * rootWriteFile = NULL;


if((NULL == filePathName) || (logLevel < 1) ||

(logLevel > 8))

{

return -1;

}


rootWriteFile = cJSON_CreateObject();

if (rootWriteFile)

{

cJSON_AddNumberToObject(rootWriteFile,"level",logLevel);

char *fileStream = cJSON_Print(rootWriteFile); //convert json to buf


FILE *fid;

fid = fopen(filePathName,"w");

if (!fid)

{

printf("open file faild \n");

nRet = -1;

}


nRet = fwrite(fileStream, sizeof(char), strlen(fileStream), fid);

if (!nRet)

{

printf("写出文件出错\n");

nRet = -1;

}


nRet = fclose(fid);

if (nRet)

{

printf("close fileFd faild \n");

nRet = -1;

}

}

else

{

nRet = -1;

}


if (rootWriteFile)

{

cJSON_Delete(rootWriteFile);

rootWriteFile = NULL;

}


return nRet;

}

注意一下JSON的空间释放

2. 客户端

客户端主要是读取一个JSON文件,然后发送

之后接收服务器响应的JSON数据:在原有数据基础上添加成功与否的标志

具体测试程序:

int main(void)

{

FILE *fid;

fid = fopen("/home/dh/workSpace/Learn/cJSON/testCJSON/clientSendData/bin/test.json","r");

if(fid == NULL)

{

printf("读取文件出错");

return -1;

}


//获取文件大小

fseek (fid , 0 , SEEK_END);

int lSize = ftell(fid);

rewind (fid);

//开辟存储空间

int num = lSize/sizeof(char);

char *jsonData = (char*) malloc (sizeof(char)*num);

if (jsonData == NULL)

{

printf("开辟空间出错\n");

return -1;

}


fread(jsonData,sizeof(char),num,fid);


// if(NULL != jsonData)

// {

// free(jsonData); //释放内存

// }


fclose(fid);


// 定义socket

int sockfd = socket(AF_INET,SOCK_STREAM,0);

// 定义sockaddr_in

struct sockaddr_in skaddr;

skaddr.sin_family = AF_INET;

skaddr.sin_port = htons(PORT);

skaddr.sin_addr.s_addr = inet_addr(SERV);


if( connect(sockfd,(struct sockaddr *)&skaddr, sizeof(skaddr)) < 0 )

{

printf("connect error \n");

exit(1);

}

printf("connect server success !!! \n");


char sendbuf[BUFF] = {0};

char recvbuf[BUFF] = {0};


// while( fgets(sendbuf, sizeof(sendbuf), stdin) != NULL )

// {

// send(sockfd, sendbuf, strlen(sendbuf), 0);

// if( strcmp(sendbuf,"exit\n") == 0)

// {

// break;

// }

// }


while( 1 )

{

int sendSize = send(sockfd, jsonData, strlen(jsonData), 0);

printf("send size %d \n", sendSize);


//usleep(1000);


int recvSize = recv(sockfd, recvbuf, sizeof(recvbuf), 0);

while (-1 == recvSize)

{

recvSize = recv(sockfd, recvbuf, sizeof(recvbuf), 0);

}


if(recvSize > 0)

{

printf("recv data size %d \n", recvSize);


cJSON *parseRoot = NULL;

parseRoot = cJSON_Parse(recvbuf);

char *out = cJSON_Print(parseRoot); //将json形式打印成正常字符串形式

printf("%s \n",out);


if(parseRoot)

{

cJSON_Delete(parseRoot);

parseRoot = NULL;

}

}


}


close(sockfd);


puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */

return EXIT_SUCCESS;

}

3. 程序效果

VBfUbmr.png!web

QRzMvma.png!web

4. 小结

编译JSON时需要链接 linux 的数学库

自己琢磨如何拆解函数功能

应用程序也主要是调用别人的api,那么你的核心竞争力是什么呢 ?

如需程序工程可在公众号后台留言。

请保持对经济的敏感性,如白酒基金、医药基金等连续几个月的上涨,自己是否无动于衷?当然需要有自己的投资方式与风格。

MZzeIjR.png!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK