简单的客户端服务器(多线程)基于json通信

news2025/1/23 3:50:14

这是一个客户端和服务器通信的小项目,小编自己手写了一个json工具,测试比jsoncpp,protobuf "效率更高"(浅拷贝),改写成深拷贝效率会急剧下降(小编能力有限,知识点(多线程,json,c++11(万能模板,完美转发,包装器等),网络套接字)

改进:后序可以引进多线程,epoll模型(反应堆)或者引入负载均衡(并发数量大的情况),Json API更加完善。

Json/json.h

#pragma once
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <fstream>
#include <unordered_map>
using namespace std;

namespace yazi
{
    namespace json
    {
        class Json
        {
        public:
            typedef std::vector<Json>::iterator iterator;
            iterator begin()
            {
                return _vaule._array->begin();
            }
            iterator end()
            {
                return _vaule._array->end();
            }
            enum Type
            {
                json_null = 0,
                json_bool,
                json_int,
                json_double,
                json_string,
                json_array,
                json_object
            };
            Json();
            Json(bool vaule);
            Json(int vaule);
            Json(double vaule);
            Json(const char* vaule);
            Json(const std::string& vaule);
            Json(Type type);
            Json(const Json& other);

            operator bool();
            operator int();
            operator double();
            operator string();
            Json& operator[](int index);
            Json& operator[](const char* key);
            Json& operator[](const std::string& key);
            void operator=(const Json& other);
            bool operator==(const Json& other);
            bool operator!=(const Json& other);
            //Json& operator*();
            void append(const Json& other);
            size_t size() const;
            string str()const;
            void copy(const Json& other);
            void clear();
            bool isNull()const { return _type == json_null; }
            bool isBool()const { return _type == json_bool; }
            bool isInt()const { return _type == json_int; }
            bool isDouble()const { return _type == json_double; }
            bool isString()const { return _type == json_string; }
            bool isArray()const { return _type == json_array; }
            bool isObject()const { return _type == json_object; }

            bool asBool() const;
            int asInt()const;
            double asDouble()const;
            std::string asString()const;


            bool has(int index);
            bool has(const char* key);
            bool has(const std::string& key);


            void remove(int index);
            void remove(const char* key);
            void remove(const std::string& key);


            void parse(const std::string& str);
        private: 
            union Vaule
            {
                bool _bool;
                int _int;
                double _double;
                std::string* _string;
                std::vector<Json>* _array;
                std::map<std::string, Json>* _object;
            };
            Type _type;
            Vaule _vaule;
        };
    }
}

json/json.cc

#include "json.h"
#include "parser.h"
using namespace yazi::json;

Json::Json() : _type(json_null)
{
}
Json::Json(bool vaule) : _type(json_bool)
{
    _vaule._bool = vaule;
}
Json::Json(int vaule) : _type(json_int)
{
    _vaule._int = vaule;
}
Json::Json(double vaule) : _type(json_double)
{
    _vaule._double = vaule;
}
Json::Json(const char* vaule) : _type(json_string)
{
    _vaule._string = new std::string(vaule);
}
Json::Json(const std::string& vaule) : _type(json_string)
{
    _vaule._string = new std::string(vaule);
}
Json::Json(Type type) : _type(type)
{
    switch (_type)
    {
    case json_null:
        break;
    case json_bool:
        _vaule._bool = false;
        break;
    case json_int:
        _vaule._int = 0;
        break;
    case json_double:
        _vaule._double = 0.0;
        break;
    case json_string:
        _vaule._string = new std::string("");
        break;
    case json_array:
        _vaule._array = new std::vector<Json>();
        break;
    case json_object:
        _vaule._object = new std::map<std::string, Json>();
        break;
    default:
        break;
    }
}
Json::Json(const Json& other)
{
    copy(other);
}

Json::operator bool()
{
    if (_type != json_bool)
    {
        throw new logic_error("type error,not bool vaule");
    }
    return _vaule._bool;
}
Json::operator int()
{
    if (_type != json_int)
    {
        throw new logic_error("type error,not int vaule");
    }
    return _vaule._int;
}
Json::operator double()
{
    if (_type != json_double)
    {
        throw new logic_error("type error,not double vaule");
    }
    return _vaule._double;
}
Json::operator string()
{
    if (_type != json_string)
    {
        throw new logic_error("type error,not  string vaule");
    }
    return *(_vaule._string);
}

Json& Json::operator[](int index)
{
    if (_type != json_array)
    {
        clear();
        _type = json_array;
        _vaule._array = new std::vector<Json>();
    }
    // if(index < 0)
    // {
    //     throw new logic_error("array[] index < 0");
    // }
    size_t size = (_vaule._array)->size();
    if (index >= size) // 扩容
    {
        for (size_t i = size; i <= index; ++i)
        {
            (_vaule._array)->push_back(Json());
        }
    }
    return (_vaule._array)->at(index);
}
Json& Json::operator[](const char* key)
{
    std::string name(key);
    return (*(this))[name];
}
Json& Json::operator[](const std::string& key)
{
    if (_type != json_object)
    {
        clear();
        _type = json_object;
        _vaule._object = new std::map<std::string, Json>();
    }
    return (*(_vaule._object))[key];
}
void Json::operator=(const Json& other)
{
    clear();
    copy(other);
}
void Json::append(const Json& other)
{
    if (_type != json_array)
    {
        _type = json_array;
        _vaule._array = new std::vector<Json>();
    }
    (_vaule._array)->push_back(other);
}
size_t Json::size() const
{
    if (_type != json_array)
    {
        throw new logic_error("type error,not array vaule");
    }
    return (_vaule._array)->size();
}
string Json::str() const
{
    std::stringstream ss;
    switch (_type)
    {
    case json_null:
        ss << "null";
        break;
    case json_bool:
        if (_vaule._bool)
        {
            ss << "true";
        }
        else
        {
            ss << "false";
        }
        break;
    case json_int:
        ss << _vaule._int;
        break;
    case json_double:
        ss << _vaule._double;
        break;
    case json_string:
        ss << '\"' << *(_vaule._string) << '\"';
        break;
    case json_array:
    {
        ss << '[';
        for (auto it = (_vaule._array)->begin(); it != (_vaule._array)->end(); ++it)
        {
            if (it != (_vaule._array)->begin())
            {
                ss << ',';
            }
            ss << it->str();
        }
        ss << ']';
        break;
    }
    case json_object:
    {
        ss << '{';
        for (auto it = (_vaule._object)->begin(); it != (_vaule._object)->end(); ++it)
        {
            if (it != (_vaule._object)->begin())
            {
                ss << ',';
            }
            ss << '\"' << it->first << '\"' << ':' << it->second.str();
        }
        ss << '}';
        break;
    }
    default:
        break;
    }
    return ss.str();
}
void Json::copy(const Json& other)
{
    _type = other._type;
    switch (_type)
    {
    case json_null:
        break;
    case json_bool:
        _vaule._bool = other._vaule._bool;
        break;
    case json_int:
        _vaule._int = other._vaule._int;
        break;
    case json_double:
        _vaule._double = other._vaule._double;
        break;
    case json_string:
        _vaule._string = other._vaule._string;
        break;
    case json_array:
        _vaule._array = other._vaule._array;
        break;
    case json_object:
        _vaule._object = other._vaule._object;
        break;
    default:
        break;
    }
}
void Json::clear()
{
    switch (_type)
    {
    case json_null:
        break;
    case json_bool:
        _vaule._bool = false;
        break;
    case json_int:
        _vaule._int = 0;
        break;
    case json_double:
        _vaule._double = 0.0;
        break;
    case json_string:
        delete _vaule._string;
        break;
    case json_array:
    {
        for (auto it = _vaule._array->begin(); it != _vaule._array->end(); ++it)
        {
            it->clear();
        }
        delete _vaule._array;
        break;
    }
    case json_object:
    {
        for (auto it = _vaule._object->begin(); it != _vaule._object->end(); ++it)
        {
            (it->second).clear();
        }
        delete _vaule._object;
        break;
    }
    default:
        break;
    }
    _type = json_null;
}

bool Json::operator==(const Json& other) //浅拷贝(效率)
{
    if (_type != other._type)
    {
        return false;
    }
    switch (_type)
    {
    case json_null:
        return true;
    case json_bool:
        return _vaule._bool == other._vaule._bool;
    case json_int:
        return _vaule._int == other._vaule._int;
    case json_double:
        return _vaule._double == other._vaule._double;
    case json_string:
        return *(_vaule._string) == *(other._vaule._string);
    case json_array:
    {
       /*if(_vaule._array->size() != other._vaule._array->size())
       {
           return false;
       }
       for (size_t i = 0; i < _vaule._array->size(); ++i)
       {
           if ((*(_vaule._array))[i] != (* (other._vaule._array))[i])
           {
               return false;
           }
       }
       return true;*/
        return _vaule._array == other._vaule._array;
    }
    case json_object:
    {
        return _vaule._object == other._vaule._object;
    }
    default:
        break;
    }
    return false;
}
bool Json::operator!=(const Json& other)
{
    return !(*this == other);
}
bool Json::asBool() const
{
    if (_type != json_bool)
    {
        throw new std::logic_error("type error,not bool vaule");
    }
    return _vaule._bool;
}
int Json::asInt()const
{
    if (_type != json_int)
    {
        throw new std::logic_error("type error,not int vaule");
    }
    return _vaule._int;
}
double Json::asDouble()const
{
    if (_type != json_double)
    {
        throw new std::logic_error("type error,not double vaule");
    }
    return _vaule._double;
}
std::string Json::asString()const
{
    if (_type != json_string)
    {
        throw new std::logic_error("type error,not string vaule");
    }
    return *(_vaule._string);
}
bool Json::has(int index)
{
    if (_type != json_array)
    {
        return false;
    }
    int size = static_cast<int>((_vaule._array)->size());
    return (index >= 0 && index < size);
}
bool Json::has(const char* key)
{
    string name(key);
    return has(name);
}
bool Json::has(const std::string& key)
{
    if (_type != json_object)
    {
        return false;
    }
    return (_vaule._object)->find(key) != (_vaule._object)->end();
}

void Json::remove(int index)
{
    if (_type != json_array)
    {
        return;
    }
    int size = static_cast<int>((_vaule._array)->size());
    if (index < 0 || index >= size)
    {
        return;
    }
    (_vaule._array)->at(index).clear();
    (_vaule._array)->erase((_vaule._array)->begin() + index);
}
void Json::remove(const char* key)
{
    string name(key);
    return remove(name);
}
void Json::remove(const std::string& key)
{
    auto it = (_vaule._object)->find(key);
    if (it == (_vaule._object)->end())
    {
        return;
    }
    (*(_vaule._object))[key].clear();
    (_vaule._object)->erase(key);
}

void Json::parse(const std::string& str)
{
    Parser p;
    p.load(str);
    *this = p.parse();
}

json/parser.h

#pragma once
#include "json.h"
#include <string>
#include <regex>
namespace yazi
{
    namespace json
    {
        class Parser
        {
        public:
            Parser();
            void load(const std::string& str);
            Json parse();
        private:
            void skip_white_space();
            char get_next_token();
            Json parse_null();
            Json parse_bool();
            Json parse_number();
            std::string parse_string();
            Json parse_array();
            Json parse_object();
        private:
            std::string _str;
            int _index;
        };
    }
}

json.parser.cc

#include "parser.h"
using namespace yazi::json;
Parser::Parser() : _str(""), _index(0)
{
}
void Parser::load(const std::string& str)
{
    _str = str;
    _index = 0;
}
Json Parser::parse()
{
    char ch = get_next_token();
    switch (ch)
    {
    case 'n':
        --_index;
        return parse_null();
    case 't':
    case 'f':
        --_index;
        return parse_bool();
    case '-':
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
        --_index;
        return parse_number();
    case '"':
        return Json(parse_string());
    case '[':
        return parse_array();
    case '{':
        return parse_object();
    default:
        break;
    }
    throw new std::logic_error("unexpected char");
}
void Parser::skip_white_space()
{
    while (_str[_index] == ' ' || _str[_index] == '\n' || _str[_index] == '\r' || _str[_index] == '\t')
    {
        ++_index;
    }
}
char Parser::get_next_token()
{
    skip_white_space();
    return _str[_index++];
}
Json Parser::parse_null()
{
    if (_str.compare(_index, 4, "null") == 0)
    {
        _index += 4;
        return Json();
    }
    throw new std::logic_error("parse null error");
}
Json Parser::parse_bool()
{
    if (_str.compare(_index, 4, "true") == 0)
    {
        _index += 4;
        return Json(true);
    }
    else if (_str.compare(_index, 5, "false") == 0)
    {
        _index += 5;
        return Json(false);
    }
    else
    {
        throw new std::logic_error("parse bool error");
    }
}
Json Parser::parse_number()
{
    int pos = _index;
    if (_str[_index] == '-')
    {
        ++_index;
    }
    if (isdigit(_str[_index]) == 0)
    {
        throw new std::logic_error("parse number error");
    }
    while (isdigit(_str[_index]) != 0)
    {
        ++_index;
    }
    if (_str[_index] != '.')
    {
        int i = std::atoi(_str.c_str() + pos);
        return Json(std::move(i));
    }
    if (isdigit(_str[++_index]) == 0)
    {
        throw new std::logic_error("parse number error");
    }
    while (isdigit(_str[_index]) != 0)
    {
        ++_index;
    }
    double f = std::atof(_str.c_str() + pos);
    return Json(std::move(f));
}
std::string Parser::parse_string()
{
    std::string out;
    while (true)
    {
        char ch = _str[_index++];
        if (ch == '"')
        {
            break;
        }
        if (ch == '\\')
        {
            ch = _str[_index++];
            switch (ch)
            {
            case '\n':
                out += '\n';
                break;
            case '\r':
                out += '\r';
                break;
            case '\t':
                out += '\t';
                break;
            case '\b':
                out += '\b';
                break;
            case '\f':
                out += '\f';
                break;
            case '"':
                out += "\\\"";
                break;
            case '\\':
                out += "\\\\";
                break;
            case 'u':
                out += "\\u";
                for (int i = 0; i < 4; ++i)
                {
                    out += _str[_index++];
                }
                break;
            default:
                break;
            }
        }
        else
        {
            out += ch;
        }
    }
    return std::move(out);
}
Json Parser::parse_array()
{
    Json arr(Json::json_array);
    char ch = get_next_token();
    if (ch == ']')
    {
        return arr;
    }
    --_index;
    while (true)
    {
        arr.append(parse());   //递归解析
        ch = get_next_token();
        if (ch == ']')
        {
            break;
        }
        if (ch != ',')
        {
            throw new std::logic_error("parse array error");
        }
        //++_index;//ERROR
    }
    return arr;
}
Json Parser::parse_object()
{
    Json obj(Json::json_object);
    char ch = get_next_token();
    if(ch == '}')
    {
        return obj;
    }
    --_index;
    while(true)
    {
        ch = get_next_token();
        if(ch != '"')
        {
            throw new std::logic_error("parse object error");
        }
        std::string key = parse_string();
        ch = get_next_token();
        if(ch != ':')
        {
            throw new std::logic_error("parse object error");
        }
        obj[key] = parse();
        ch = get_next_token();
        if(ch == '}')
        {
            break;
        }
        if(ch != ',')
        {
            throw new std::logic_error("parse object error");
        }
        //++_index;//ERROR
    }
    return obj;
}

tcp_socket.hpp

#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <cassert>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "./json/json.h"
#include "./json/parser.h"
using namespace yazi::json;
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
#define CHECK_RET(exp) \
    if (!(exp))        \
    {                  \
        return false;  \
    }
class TcpSocket
{
public:
    TcpSocket() : fd_(-1) {}
    TcpSocket(int fd) : fd_(fd) {}
    bool Socket()
    {
        fd_ = socket(AF_INET, SOCK_STREAM, 0);
        if (fd_ < 0)
        {
            perror("socket");
            return false;
        }
        printf("open fd = %d\n", fd_);
        return true;
    }
    bool Close() const
    {
        close(fd_);
        printf("close fd = %d\n", fd_);
        return true;
    }
    bool Bind(const std::string &ip, uint16_t port) const
    {
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);
        int ret = bind(fd_, (sockaddr *)&addr, sizeof(addr));
        if (ret < 0)
        {
            perror("bind");
            return false;
        }
        return true;
    }
    bool Listen(int num) const
    {
        int ret = listen(fd_, num);
        if (ret < 0)
        {
            perror("listen");
            return false;
        }
        return true;
    }
    bool Accept(TcpSocket *peer, std::string *ip = NULL, uint16_t *port = NULL) const
    {
        sockaddr_in peer_addr;
        socklen_t len = sizeof(peer_addr);
        int new_sock = accept(fd_, (sockaddr *)&peer_addr, &len);
        if (new_sock < 0)
        {
            perror("accept");
            return false;
        }
        printf("accept fd = %d\n", new_sock);
        peer->fd_ = new_sock;
        if (ip != NULL)
        {
            *ip = inet_ntoa(peer_addr.sin_addr);
        }
        if (port != NULL)
        {
            *port = ntohs(peer_addr.sin_port);
        }
        return true;
    }
    bool Recv(std::string *buf) const
    {
        buf->clear();
        char tmp[1024 * 10] = {0};
        // [注意!] 这里的读并不算很严谨, 因为一次 recv 并不能保证把所有的数据都全部读完
        // 参考 man 手册 MSG_WAITALL 节.
        ssize_t read_size = recv(fd_, tmp, sizeof(tmp), 0);
        if (read_size < 0)
        {
            perror("recv");
            return false;
        }
        if (read_size == 0)
        {
            return false;
        }
        buf->assign(tmp, read_size);
        return true;
    }
    bool Recv(Json* result) const
    {
        result->clear();
        char tmp[1024 * 10] = {0};
        ssize_t read_size = recv(fd_, tmp, sizeof(tmp), 0);
        if (read_size < 0)
        {
            perror("recv");
            return false;
        }
        if (read_size == 0)
        {
            return false;
        }
        std::string name(tmp);
        (*result).parse(name);
        return true;
    }
    bool Send(const std::string &buf) const
    {
        ssize_t write_size = send(fd_, buf.data(), buf.size(), 0);
        if (write_size < 0)
        {
            perror("send");
            return false;
        }
        return true;
    }
    bool Send(const Json &vaule) const
    {
        ssize_t write_size = send(fd_, vaule.str().data(), vaule.str().size(), 0);
        if (write_size < 0)
        {
            perror("send");
            return false;
        }
        return true;
    }
    bool Connect(const std::string &ip, uint16_t port) const
    {
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);
        int ret = connect(fd_, (sockaddr *)&addr, sizeof(addr));
        if (ret < 0)
        {
            perror("connect");
            return false;
        }
        return true;
    }
    int GetFd() const
    {
        return fd_;
    }

private:
    int fd_;
};

tcp_client.hpp        

#pragma once
#include "tcp_socket.hpp"
class TcpClient
{
public:
    TcpClient(const std::string &ip, uint16_t port) : ip_(ip), port_(port)
    {
        // [注意!!] 需要先创建好 socket
        sock_.Socket();
    }
    ~TcpClient()
    {
        sock_.Close();
    }
    bool Connect()
    {
        return sock_.Connect(ip_, port_);
    }
    bool Recv(std::string *buf)
    {
        return sock_.Recv(buf);
    }
    bool Recv(Json* result)
    {
        return sock_.Recv(result);
    }
    bool Send(const std::string &buf)
    {
        return sock_.Send(buf);
    }
    bool Send(const Json& vaule)
    {
        return sock_.Send(vaule);
    }
private:
    TcpSocket sock_;
    std::string ip_;
    uint16_t port_;
};

tcp_server.hpp

#pragma once
#include <functional>
#include <pthread.h>
#include "tcp_socket.hpp"
typedef std::function<void(const std::string &, std::string *)> Handler;
struct ThreadArg
{
    TcpSocket new_sock;
    std::string ip;
    uint16_t port;
    Handler handler;
};
class TcpThreadServer
{
public:
    TcpThreadServer(const std::string &ip, uint16_t port) : ip_(ip), port_(port)
    {
    }
    bool Start(Handler handler)
    {
        // 1. 创建 socket;
        CHECK_RET(listen_sock_.Socket());
        // 2. 绑定端口号
        CHECK_RET(listen_sock_.Bind(ip_, port_));
        // 3. 进行监听
        CHECK_RET(listen_sock_.Listen(5));
        // 4. 进入循环
        for (;;)
        {
            // 5. 进行 accept
            ThreadArg *arg = new ThreadArg();
            arg->handler = handler;
            bool ret = listen_sock_.Accept(&arg->new_sock, &arg->ip, &arg->port);
            if (!ret)
            {
                continue;
            }
            printf("[client %s:%d] connect\n", arg->ip.c_str(), arg->port);
            // 6. 创建新的线程完成具体操作
            pthread_t tid;
            pthread_create(&tid, NULL, ThreadEntry, arg);
            pthread_detach(tid);
        }
        return true;
    }
    // 这里的成员函数为啥非得是 static?
    static void *ThreadEntry(void *arg)
    {
        // C++ 的四种类型转换都是什么?
        ThreadArg *p = reinterpret_cast<ThreadArg *>(arg);
        ProcessConnect(p);
        // 一定要记得释放内存!!! 也要记得关闭文件描述符
        p->new_sock.Close();
        delete p;
        return NULL;
    }
    // 处理单次连接. 这个函数也得是 static
    static void ProcessConnect(ThreadArg *arg)
    {
        // 1. 循环进行读写
        for (;;)
        {
            std::string req;
            // 2. 读取请求
            bool ret = arg->new_sock.Recv(&req);
            if (!ret)
            {
                printf("[client %s:%d] disconnected!\n", arg->ip.c_str(), arg->port);
                break;
            }
            std::string resp;
            // 3. 根据请求计算响应
            arg->handler(req, &resp);
            // 4. 发送响应
            arg->new_sock.Send(resp);
            printf("[client %s:%d] req: %s, resp: %s\n", arg->ip.c_str(),
                   arg->port, req.c_str(), resp.c_str());
        }
    }

private:
    TcpSocket listen_sock_;
    std::string ip_;
    uint16_t port_;
};

 dict_client.cc

#include "tcp_client.hpp"
#include <iostream>
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf("Usage ./dict_client [ip] [port]\n");
        return 1;
    }
    TcpClient client(argv[1], atoi(argv[2]));
    bool ret = client.Connect();
    if (!ret)
    {
        return 1;
    }
    // for (;;)
    // {
    //     std::cout << "请输入要查询的单词:" << std::endl;
    //     std::string word;
    //     std::cin >> word;
    //     if (!std::cin)
    //     {
    //         break;
    //     }
    //     client.Send(word);
    //     std::string result;
    //     client.Recv(&result);
    //     std::cout << result << std::endl;
    // }
    for (;;)  //客户端创建json串发往服务器
    {
        std::cout << "请输入你的协议:" << std::endl;
        // const std::string& str = "{\"a\":true,\"b\":{\"a\":true,\"b\":[1, \"a\", 3, null, -1.2345, true, false, \"hello world\"],\"c\":123,\"4\":\"hello world\"},\"c\":123,\"4\":\"hello world\"}";
        // Json v;
        // v.parse(str);
        // std::cout << v.str() << std::endl;
        // client.Send(v.str());
        Json arr;
        arr[1] = true;
        arr[2] = 123;
        arr[3] = 1.23;
        arr[4] = "hello";
        Json obj;
        obj["bool"] = true;
        obj["int"] = 123;
        obj["double"] = 1.23;
        obj["arr"] = arr;
        std::cout << obj.str() << std::endl;
        client.Send(obj);
        obj.clear();

        Json result;
        // client.Recv(result);
        // std::string result;
        client.Recv(&result);
        std::cout << result.str() << std::endl;
    }
    return 0;
}

dict_server.cc

#include <unordered_map>
#include "tcp_server.hpp"
#include "./json/json.h"
#include "./json/parser.h"
std::unordered_map<std::string, std::string> g_dict;
// void Translate(const std::string &req, std::string *resp)
// {
//     auto it = g_dict.find(req);
//     if (it == g_dict.end())
//     {
//         *resp = "未找到";
//         return;
//     }
//     *resp = it->second;
//     return;
// }
void Translate(const std::string &req, std::string *resp)
{
    // auto it = g_dict.find(req);
    // if (it == g_dict.end())
    // {
    //     *resp = "未找到";
    //     return;
    // }
    // *resp = it->second;
    // return;

    Json vaule;
    vaule.parse(req);
    if(vaule["bool"])
    {
        Json obj;
        //收到Json串这里可以有服务器自己处理业务
        //obj["服务器"] = "收到了";
        Json arr;
        arr[0] = "服务器收到客户端的数据了";
        arr[1] = "服务器发往客户端的协议为:932";
        arr[2] = 932;
        obj["服务器"] = arr;
        *resp = obj.str();
        obj.clear();
    }
    vaule.clear();
}
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf("Usage ./dict_server [ip] [port]\n");
        return 1;
    }
    // 1. 初始化词典
    //g_dict.insert(std::make_pair("hello", "你好"));
    //g_dict.insert(std::make_pair("world", "世界"));
    //g_dict.insert(std::make_pair("bit", "贼NB"));
    // 2. 启动服务器
    TcpThreadServer server(argv[1], atoi(argv[2]));
    server.Start(Translate);
    return 0;
}

makefile

.PHONY:all
all:dict_client dict_server
dict_client:dict_client.cc ./json/json.cc ./json/parser.cc
dict_client.cc:
	g++ -o $@  $^ -std=c++11
dict_server:dict_server.cc ./json/json.cc ./json/parser.cc
	g++ -o $@ $^  -std=c++11 -lpthread
.PHONY:clean
clean:
	rm -rf dict_client dict_server

测试截图:

 

 

githup地址: 

 基于Josn的网络通信

josn工具

protobuf工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/151490.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

技术分享 | Spring Boot 异常处理

说到异常处理&#xff0c;我们都知道使用 try-catch 可以捕捉异常&#xff0c;可以 throws 抛出异常。那么在 Spring Boot 中我们如何处理异常&#xff0c;如何更优雅的处理异常&#xff0c;如何全局处理异常。是本章讨论解决的问题。Java 异常类首先让我们简单了解或重新学习下…

Android开发-AS学习(一)

完整项目最精简流程&#xff1a;Android <-> 接口 <-> 数据库Android开发工具&#xff1a;Android Studio项目目录信息&#xff1a;一、控件1.1 TextView基础属性描述layout_width组件的宽度layout_height组件的高度id为TextView设置一个组件idtext设置显示的文本内…

Linux 学习笔记(借鉴黑马程序员Linux课程)

Linux视频课程 简介 Linux诞生于1991年&#xff0c;由林纳斯托瓦兹在21岁时完成。此后成为最为流行的服务器操作系统之一。 Linux内核和系统发行版 由Linux系统内核和系统级应用程序两部分组成。 内核提供系统最核心的功能&#xff0c;如&#xff1a;调度CPU、调度内存、调…

【笑小枫的按步照搬系列】Redis多系统安装(Windows、Linux、Ubuntu)

笑小枫&#x1f495; 欢迎来到笑小枫的世界&#xff0c;喜欢的朋友关注一下我呦&#xff0c;大伙的支持&#xff0c;就是我坚持写下去的动力。 微信公众号&#xff1a;笑小枫 笑小枫个人博客&#xff1a;https://www.xiaoxiaofeng.com Windows 下安装 方式一&#xff1a;https…

HCL(新华三模拟器)如何连接CRT及改界面颜色

我使用的HCL版本是2.1.1官网下载连接&#xff1a;https://www.h3c.com/cn/Service/Document_Software/Software_Download/Other_Product/H3C_Cloud_Lab/Catalog/HCL/&#xff0c;一键直达下载官网这个版本可以适配virtualbox的5.2.44的版本&#xff0c;同时支持华为的ensp模拟器…

Spring Security 表单配置(一)

Spring Security 表单配置&#xff08;一&#xff09;工具版本及环境参考资源配置详细说明工具版本及环境 工具&#xff1a; IDEA 2021.3 Maven 3.8.6 JDK 8 Spring Boot 2.7.7 Spring Securiity 5.7.6 参考资源 Spring Security官网: https://docs.spring.io/spring-security…

javaEE 初阶 — 常见的锁策略

文章目录1. 乐观锁 vs 悲观锁2. 互斥锁 vs 读写锁3. 重量级锁 vs 轻量级锁4. 自旋锁 vs 挂起等待锁5. 公平锁 vs 非公平锁6. 可重入锁 vs 不可重入锁7. synchronized 是哪种锁8. 相关面试题1. 乐观锁 vs 悲观锁 乐观锁 指的是预测锁竞争不是很激烈&#xff0c;也就是指这里做的…

排列组合两个列表中的元素 product(a,b)

【小白从小学Python、C、Java】【计算机等级考试500强双证书】【Python-数据分析】排列组合两个列表中的元素product(a,b)关于以下python代码表述错误的一项是?from itertools import producta [1,2,3]b [4,5,6]print("【显示】a",a)print("【显示】b",…

修改Keil开发环境背景(修改为黑色主题)

修改Keil开发背景&#xff08;修改为黑色主题&#xff09;引言步骤总结引言 我们平时在Keil uVision5下开发单片机/嵌入式程序的时候&#xff0c;如果始终用的是官方的主题背景&#xff0c;往往会因为背景太白了&#xff0c;而导致视疲劳。我们使用VSCode往往不会有这种困扰&a…

Python处理字符串 中文(汉字)编码示例

在实际开发中&#xff0c;发现打印Python打印经常出现乱码&#xff0c;大部分都是编码引起&#xff0c;这里只是简单说一下utf-8/ gbk/ unicode编码之间的相互转换问题&#xff1a; utf-8是Unix下的一种通用编码&#xff0c;gbk是win环境下的一种汉字编码&#xff0c;unicode是…

计算机组成原理_总线仲裁

计算机组成原理总目录总线仲裁 由于总线连接着多个设备&#xff0c;那么在同一时刻多个设备想要占用总线时&#xff0c;就会发生冲突问题 为了解决冲突问题&#xff0c;就需要规定好所有设备使用设备的优先权&#xff0c;仲裁也就是判断设备占用总线的优先权 例如设备A的任务比…

Docker--安装mysql8--方法/步骤

原文网址&#xff1a;Docker--安装mysql8--方法/步骤_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何使用docker安装mysql8。 查看mysql版本 https://hub.docker.com/_/mysql/tags 我选择8.0&#xff0c;点击右侧箭头处直接复制命令。 拉取镜像 拉取镜像的命令 docker pul…

RADIANT:一种全新的雷达图像关联网络用于3D目标检测

RADIANT&#xff1a;一种全新的雷达图像关联网络用于3D目标检测 论文地址&#xff1a;RADIANT: Radar-Image Association Network for 3D Object Detection 源码&#xff1a;https://github.com/longyunf/radiant 单位&#xff1a;密歇根大学、福特 动机 作为一种能够直接…

全景剖析阿里云容器网络数据链路(二):Terway EN

作者&#xff1a;余凯 本系列文章由余凯执笔创作&#xff0c;联合作者&#xff1a;阿里云容器服务 谢石 对本文亦有贡献 前言 近几年&#xff0c;企业基础设施云原生化的趋势越来越强烈&#xff0c;从最开始的 IaaS 化到现在的微服务化&#xff0c;客户的颗粒度精细化和可观…

使用小度音箱+Blinker控制ESP01S Relay继电器模块

一. 使用ESP01S模块&#xff0c;PIN脚定义如下&#xff1a; 管脚功能如下&#xff1a; ESP01S模块原理图&#xff1a; ESP01S模块比ESP01模块做了以下优化&#xff1a; LED灯的管脚发生变化&#xff0c;由ESP01的TXD0变成ESP01s的GPIO2引脚&#xff1b;ESP01s模块的IO0、RST、…

Java开发 - Spring MVC框架初体验

前言 上一篇Spring框架感觉写的偏向于理论知识&#xff0c;所以从这篇开始&#xff0c;转变此系列的写作思维&#xff0c;更多的将从实操的角度来讲解Spring MVC框架的使用和相关知识点&#xff0c;会尽量详细&#xff0c;但这一系列课程针对的还是有Java基础的小伙伴&#xf…

树莓派上如何安装anaconda/miniconda环境配置

目录1. 前言2. miniconda下载3. miniconda 安装4. 添加 .bashrc 配置5. Conda 更换源&#xff0c;软件更新6. 部分问题及解决方案报错一&#xff1a;报错二&#xff1a;报错三&#xff1a;7. 卸载miniconda8. 版本问题/注意事项1. 前言 在装完树莓派之后&#xff0c;当你想要使…

()智能指针一) shared_ptr

智能指针(一) 文章目录智能指针(一)shared_ptr1初始化方式make_ptr<>() 和 shared_ptr<>() 的区别shared_ptr维护引用计数需要的信息使用原始的new函数创建shared_ptr使用make_shared创建shared_ptrmake_shared实现异常安全使用make_shared的缺点make_shared 源码解…

从一个Demo说起Dubbo3

简介 2017年的9月份&#xff0c;阿里宣布重启Dubbo的开发维护&#xff0c;并且后续又将Dubbo捐献给了Apache&#xff0c;经过多年的发展已经发布到3.X版本了&#xff0c;Dubbo重启维护之后是否有值得我们期待的功能呢&#xff0c;下面就来看看吧。 Apache Dubbo 是一款微服务…

买英伟达RTX 30 系显卡送《穿越火线》大礼包,你心动了吗?

2022年下半年英伟达一口气推出了RTX 4090、4080、4070 Ti显卡&#xff0c;40系列中的4060也在准备中&#xff0c;而RTX 30 系列在新系列的光芒下显得有些暗淡。 面对40系列即将成为主流的这种情况下&#xff0c;英伟达势必要想一些办法清清30系列显卡的库存&#xff0c;于是英…