Linux Socket 收发Json

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

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

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

 

1. Server 端

使用的是socket 阻塞式,没有使用select、poll、epoll等

接收端按照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. 程序效果

4. 小结

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

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

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

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

 

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

评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值