专栏首页Pou光明Linux Socket 收发Json

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,那么你的核心竞争力是什么呢 ?

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

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

本文分享自微信公众号 - Pou光明(pou0230),作者:PouG

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Qt Socket Server 收发JSON

    之前文章写过Linux C Socket 收发Json数据,最近用Qt Server实现了一遍。给我自己的感觉就是cJSON接口与Qt封装的一些接口是共通的:Q...

    用户5908113
  • C++中消息自动派发之三 About JSON Encode

      《C++ 消息自动派发》系列上篇介绍了IDL解析器,生成的C++代码只支持JSON转C++ struct。 经过新的重构,这次增加了对C++ struct ...

    知然
  • 做游戏与web的区别 - 服务器篇【1】

    在一间游戏公司的两个部门待过, 前一个部门以做web开发为主,后一个部门做游戏开发,我在两边都是做后端的。

    用户1608022
  • 小林带你盘一盘,常用的网络命令

    服务器一般都是命令页面,不像 windows 有图形页面点点鼠标就好,所以掌握些基本的 Linux 命令是很有必要的,不然就无法操作 Linux,更体会不到 L...

    小林coding
  • python的socket编程介绍及示例

    首先要了解下socket(套接字),我们可以通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

    languageX
  • Android蓝牙开发(三)之蓝牙通信

    上篇文章:https://blog.csdn.net/huangliniqng/article/details/82187966

    黄林晴
  • Socket接口异步验证实践

    之前做过一些Socket接口的测试脚本,但是并没有对其中的响应结果进行自动化验证,主要还是靠人肉眼去检查。前天完成了JSON对象的多功能验证类VerifyBea...

    FunTester
  • 基于QMP实现对qemu虚拟机进行交互

    qemu对外提供了一个socket接口,称为qemu monitor,通过该接口,可以对虚拟机实例的整个生命周期进行管理,主要有如下功能

    小慢哥Linux运维
  • 基于WebSocket的client封装

    最近已经陷于了Socket测试的泥潭中了,之前用Java写了一个Client封装类,本想在经历过本轮测试之后,写一些文档在发出来,没想到测试对象用的是Socke...

    FunTester
  • Python基础:网络编程socket基

    因为socket是一个类,所以只导入模块需要使用socket.socket()创建一个socket对象。

    py3study
  • (六)关于网络编程的一些实用技巧和细节

    这些年,接触了形形色色的项目,写了不少网络编程的代码,从windows到linux,跌进了不少坑,由于网络编程涉及很多细节和技巧,一直想写篇文章来总结下这方面的...

    范蠡
  • (六)关于网络编程的一些实用技巧和细节

    这些年,接触了形形色色的项目,写了不少网络编程的代码,从windows到linux,跌进了不少坑,由于网络编程涉及很多细节和技巧,一直想写篇文章来总结下这方面的...

    范蠡
  • TCP 异常关闭研究分析

    最近发现连接异常断开时TCP的错误码大部分是 104 或 10054(Windows下),单纯从错误码本来来说,大家都明白是“网络被对端重置了”,但究竟什么情况...

    云加社区
  • 打造基于Nginx的敏感信息泄露检测系统

    *本文原创作者:f4ckbaidu,本文属FreeBuf原创奖励计划,未经许可禁止转载

    FB客服
  • Python搭建HTTP服务

    本次我们要为一个自动化测试工具搭建一个HTTP服务,以方便一个本地的测试工具被大家在网络中共享使用。

    py3study
  • 5分钟入门 redis 命令行

    redis 的 windows 客户端实在难用,这次连不上还 crash 了 N 次,还是转命令行吧。搜出来的教程都是杂七杂八,不适合我这种菜鸡。

    子润先生
  • iperf3命令使用

    iperf3下载:https://iperf.fr/iperf-download.php#fedora

    py3study
  • APP自动化测试系列之Appium介绍及运行原理

    在上一篇APP自动化系列文章:APP自动化测试系列之adb连接真机和模拟器,主要介绍adb连接真机的两种方式及如何连接夜神模拟器。

    ITester软件测试小栈
  • Java TCP/UDP/HttpClient简例

    ​ 服务端socket处理客户端socket连接是需要一定时间的。ServerSocket有一个队列,存放还没有来得及处理的客户端Socket,这个队列的容量就...

    小锋学长

扫码关注云+社区

领取腾讯云代金券