栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++使用json在Linux中实现TCP通信

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++使用json在Linux中实现TCP通信

最近在学习使用json格式在Linux中进行tcp通信,以下为学习笔记

我使用的第三方库为nlohomann/json, 仓库地址为

nlohmann/json: JSON for Modern C++ (github.com)

nlohomann/json的所有代码都保存在单个头文件json.hpp中,所以要使用nlohomann/json,需要在实现文件中包含json.hpp

#include "json.hpp"
json的发送与接收

要发送json格式的数据时需要先将其转换为二进制数据,我使用以下代码实现转换

    json j;
    char sendData[2048];
    ...
    string s = j.dump();//将json转换为string类型
    strcpy(sendData, s.c_str());//将string类型转为char*后进行拷贝

在接收到json的二进制数据后,再将其转换为json格式

recv(peerfd, recvdata, 2048, 0);
json j = json::doParse(recvData);
代码实例

我封装了一个用于json与内置数据类型与STL容器转换的类

#include "json.hpp"
#include 
#include 
class ProtocolParser
{
    public:
        void Json2char(json & j, char*  sendData);//json转char数组
        json doParse(char*  recvData);//char数组转json
        json vector2json(vector & s);//vector转json
        void json2vector(json & j, vector & v);//json转vector
};

using std::string;

void ProtocolParser::Json2char(json & j, char*  sendData)
{
    string s = j.dump();
    strcpy(sendData, s.c_str());
}

json ProtocolParser::doParse(char * recvData)
{
    return json::parse(recvData);
}

json ProtocolParser::vector2json(vector & s)
{
    return json(s);
}

void ProtocolParser::json2vector(json & j, vector & v)
{
    v.clear();
    v = j.get>();
}

以下为在客户端与服务端中使用ProtocolParse类的示例

服务端

#include 
#include 
#include 
#include 
#include 
#include "json.hpp"

#include 
#include 
#include 
#include 
#include "ProtocolParser.h"

#include 
#include 
using std::cin;
using std::cout;
using std::endl;
using std::string;
using nlohmann::json;

void test()
{
  //1. 创建监听服务器的套接字
  int listenfd = ::socket(AF_INET, SOCK_STREAM, 0);  

  if(listenfd < 0)
    {
    perror("socket");
    return;
  }

  //网络地址需要采用网络字节序存储(大端模式)
  struct sockaddr_in serveraddr;
  memset(&serveraddr, 0, sizeof(serveraddr));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_port = htons(8888);
  serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  socklen_t length = sizeof(serveraddr);

#if 1
  //设置网络地址可以重用
  int on = 1;
  if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0) 
    {
    perror("setsockopt");
    close(listenfd);
    return;
  }

  //当端口设置为可以重用时, 就实现了系统级别的负载均衡
  if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)) < 0) 
    {
    perror("setsockopt");
    close(listenfd);
    return;
  }
#endif

  //2. 绑定服务器的网络地址
  if(::bind(listenfd, (struct sockaddr*)&serveraddr, length) < 0)
    {
    perror("bind");
    //文件描述符是比较稀缺的,所以不用的时候要回收
    close(listenfd);
    return;
  }

  //3. 让服务器开始监听
  if(::listen(listenfd, 10) < 0)
    {
    perror("listen");
    close(listenfd);
    return;
  } 
  printf("server is listening...n");

  //4. 获取对端的文件描述符,并与对端进行通信
  int peerfd = ::accept(listenfd, nullptr, nullptr);

  //5. 需求:希望服务器可以与客户端通过终端进行聊天
  while(1) 
    {
    char recvdata[2048];
    int ret = recv(peerfd, recvdata, 2048, 0);
    printf("recv msg from client: %sn", recvdata);
    recvdata[ret] = '';
    ProtocolParser parse;
    json j = parse.doParse(recvdata);
    cout << j << endl;

    //从终端获取一行数据
    cout << ">> pls input some message:";
    string line;
    getline(cin, line);
    send(peerfd, line.c_str(),  line.size(), 0);
  }
  
  close(peerfd);// 关闭连接
  close(listenfd);
}
 
int main(void)
{
  test();
  return 0;
}

客户端

#include 
#include 
#include 
#include 
#include 
#include "json.hpp"
#include "ProtocolParser.h"

#include 
#include 
#include 
#include 

#include 
#include 
using std::cin;
using std::cout;
using std::endl;
using std::string;
using nlohmann::json;
using std::vector;

void test()
{
  int clientfd = ::socket(AF_INET, SOCK_STREAM, 0);
  if (clientfd < 0)
  {
    perror("socket");
    return;
  }

  struct sockaddr_in serverAddr;
  memset(&serverAddr, 0, sizeof(serverAddr));
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(8888);
  serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  socklen_t length = sizeof(serverAddr);

  if (::connect(clientfd, (struct sockaddr* )&serverAddr, length) < 0)
  {
    perror("connect");
    close(clientfd);
    return;
  }
  printf("conn has connected!...n");

  while (1)
  {
    // string line;
    // cout << ">> pls input some message:";
    // getline(cin, line);
    // line.append("n");
    char sendData[2048] = {0};
    
    vector vec={"hello", "world"};
    ProtocolParser parser;
    json j = parser.vector2json(vec);
    parser.Json2char(j, sendData);
    // 1. 客户端先发数据
    send(clientfd, sendData, strlen(sendData), 0);
    

    char buff[128] = {0};
    recv(clientfd, buff, sizeof(buff), 0);
    printf("recv msg from server: %sn", buff);
  }

  close(clientfd);
}

int main(void)
{
  test();
  return 0;
}

运行结果

服务端进程

客户端进程

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/997264.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号