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,那麼你的核心競爭力是什麼呢 ?

如需程序工程可在公衆號後臺留言。

 

請保持對經濟的敏感性,如白酒基金、醫藥基金等連續幾個月的上漲,自己是否無動於衷?當然需要有自己的投資方式與風格。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章