国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【網(wǎng)絡(luò)】協(xié)議的定制與Json序列化和反序列化

這篇具有很好參考價(jià)值的文章主要介紹了【網(wǎng)絡(luò)】協(xié)議的定制與Json序列化和反序列化。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

應(yīng)用層

我們程序員寫的一個(gè)個(gè)解決我們實(shí)際問(wèn)題, 滿足我們?nèi)粘P枨蟮木W(wǎng)絡(luò)程序, 都是在應(yīng)用層

初識(shí)TCP協(xié)議通訊流程

  • 建立鏈接和斷開(kāi)鏈接

基于TCP協(xié)議,我們需要知道寫代碼時(shí)對(duì)應(yīng)的接口大概在TCP通訊的過(guò)程中屬于什么樣的時(shí)間點(diǎn)角色,在TCP協(xié)議時(shí)詳談。三次握手,四次揮手

listen狀態(tài):準(zhǔn)備好了,可以進(jìn)行鏈接,accept:獲取鏈接,不是創(chuàng)造鏈接,鏈接已經(jīng)在底層創(chuàng)建好了,在應(yīng)用層調(diào)用accept把鏈接拿上來(lái)

connect:1.發(fā)起鏈接請(qǐng)求2.綁定套接字;建立鏈接,在底層向服務(wù)端建立鏈接請(qǐng)求,在TCP中,采用鏈接的方案是三次握手的方案,connect會(huì)發(fā)起三次握手,發(fā)起鏈接請(qǐng)求和真正的建立鏈接是兩碼事,建立鏈接由雙方OS自動(dòng)完成的,為什么自動(dòng)完成?網(wǎng)絡(luò)分層中,下三層是OS內(nèi)部的,用戶感知不到。通過(guò)客戶端調(diào)用connect讓OS來(lái)幫我們把三次握手的工作做完。

而accept是獲取鏈接,鏈接是已經(jīng)建立好了的,所以accept并不參與三次握手的任何細(xì)節(jié),accept一定是在獲取鏈接前別人把鏈接做完,既鏈接建立完。三次握手是OS自己完成的,connect只是發(fā)起,accept只是收尾。即使上層不調(diào)用accept,三次握手也是能夠建立好的。

TCP保證可靠性不是write和read有關(guān)系的,由雙方OS完成的,后面詳談。

建立鏈接后面就要斷開(kāi)鏈接,所以UDP由于不需要建立鏈接,自然不需要談?wù)摂嚅_(kāi)鏈接

而四次揮手的工作都是由雙方的OS完成,而我們決定什么時(shí)候分手一旦調(diào)用系統(tǒng)調(diào)用close,用戶層就不用管了。

  • 理解鏈接

談男女朋友時(shí),都會(huì)表達(dá)自己的愛(ài)意,一定有一方主動(dòng)發(fā)起鏈接,無(wú)論如何表達(dá),雙方看對(duì)眼的概率是極低的。而主動(dòng)發(fā)起鏈接,是怎么發(fā)起的呢?首先,男方先表白,然后女方在做表態(tài),什么時(shí)候在一起?男方回答就現(xiàn)在。這就是雙方三次握手成功。(雖然現(xiàn)實(shí)生活中被拒絕是常態(tài))

建立鏈接究竟在干什么:記下一些東西

  • 什么是建立鏈接

所謂的建立鏈接,三次握手根本就是手段,不是目的,為了達(dá)到讓雙方都能記住這一套,一個(gè)服務(wù)端鏈接客戶端,很多客戶端來(lái)鏈接了,意味著很多的客戶端來(lái)了,OS應(yīng)該區(qū)分清楚,需要把鏈接管理起來(lái),先描述在組織,需要?jiǎng)?chuàng)建對(duì)應(yīng)的鏈接數(shù)據(jù)結(jié)構(gòu),把所有的鏈接描述起來(lái),在對(duì)其進(jìn)行管理。所謂的鏈接就是OS內(nèi)部創(chuàng)建的鏈接結(jié)構(gòu)體,包含了在建立鏈接時(shí)對(duì)應(yīng)的屬性信息。當(dāng)有新的鏈接進(jìn)來(lái)時(shí),每到來(lái)一個(gè)鏈接,服務(wù)端會(huì)構(gòu)建一個(gè)鏈接對(duì)象 ,將所有的鏈接對(duì)象在內(nèi)部中用特定的數(shù)據(jù)結(jié)構(gòu)管理起來(lái)。這就是鏈接的建模過(guò)程。維護(hù)鏈接是需要成本的。占用內(nèi)存資源,要用對(duì)象進(jìn)行管理。

斷開(kāi)鏈接需要四次揮手,斷開(kāi)鏈接的最終目的毫無(wú)疑問(wèn)就是把建立好的鏈接信息釋放。四次揮手理解:

男女朋友處的非常好,走到了婚姻的殿堂,但是被現(xiàn)實(shí)打敗了,過(guò)不下去啦。然后一方提出離婚,但是你自己說(shuō)了不算,另一方說(shuō)好啊,過(guò)了一會(huì),對(duì)象又說(shuō)離就離,那我也要離,那么你一看,我也OK。所以斷開(kāi)鏈接是雙方的事情,必須得征求雙方的意見(jiàn)。雙方在協(xié)商,TCP要保證可靠性,你說(shuō)的話要保證你也聽(tīng)到了,我也知道了,反之也一樣。這就是傳說(shuō)中的四次揮手

TCP與UDP對(duì)比

可靠傳輸VS不可靠傳輸

有連接VS無(wú)連接

字節(jié)流VS數(shù)據(jù)報(bào)

定制協(xié)議

應(yīng)用層協(xié)議的定制

再談協(xié)議

協(xié)議是一種約定,socket api的接口,在讀寫數(shù)據(jù)時(shí),都是按照字符串的方式來(lái)接收的,如果要傳輸一些”結(jié)構(gòu)化的數(shù)據(jù)“怎么辦呢?

結(jié)構(gòu)化的數(shù)據(jù):群里說(shuō)話的時(shí)候除了消息本身,還有頭像,昵稱時(shí)間等等信息 。但是不是一個(gè)一個(gè)獨(dú)立的個(gè)體,你需要做的把這些消息形成一個(gè)報(bào)文——打包成一個(gè)字符串。

由多變一這個(gè)過(guò)程就是序列化。經(jīng)過(guò)網(wǎng)絡(luò)傳輸后,收到的是一個(gè)報(bào)文,收到一個(gè)報(bào)文要的是什么?把一個(gè)字符串變成多個(gè)字符串,這個(gè)過(guò)程是反序列化

業(yè)務(wù)數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)的時(shí)候,先序列化發(fā)送,收到的是序列字節(jié)流,要先進(jìn)行反序列化, 然后才能使用

業(yè)務(wù)協(xié)議就是結(jié)構(gòu)體,這樣說(shuō)還是不夠的,所以我們要手寫一個(gè)協(xié)議。

應(yīng)用場(chǎng)景:形成字符串對(duì)方收到,收到之后上層來(lái)不及接收,對(duì)方又發(fā)一個(gè),有可能一次全讀的,上層如何保證收到的是一個(gè)報(bào)文?

tcp這里怎么保證收到一個(gè)完整的報(bào)文

理解業(yè)務(wù)協(xié)議,理解序列化和反序列化。

網(wǎng)絡(luò)版本計(jì)算器

例如, 我們需要實(shí)現(xiàn)一個(gè)服務(wù)器版的加法器. 我們需要客戶端把要計(jì)算的兩個(gè)加減乘除數(shù)發(fā)過(guò)去, 然后由服務(wù)器進(jìn)行計(jì)算, 最后再把結(jié)果返回給客戶端

TCP是面向字節(jié)流的,所以明確報(bào)文和報(bào)文的邊界:

【網(wǎng)絡(luò)】協(xié)議的定制與Json序列化和反序列化

TCP是全雙工的,如果接收方來(lái)不及讀,那接收緩沖區(qū)就會(huì)存在很多數(shù)據(jù),讀的時(shí)候怎么怎么保證讀到一個(gè)完整的報(bào)文:

1.定長(zhǎng)2.特殊符號(hào)3.自描述方式

序列化、反序列化與定制協(xié)議是兩碼事,是不同階段的事情,定制協(xié)議:報(bào)頭+有效載荷

Protocal.hpp

自定義協(xié)議:

#define SEP " "
#define SEP_LEN strlen(SEP)
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP)

請(qǐng)求和響應(yīng):Request,Response

Request:x,y,op(“x op y”)x和y是數(shù)據(jù),op是操作符,比如1+2

Response:設(shè)置了退出碼exitcode和結(jié)果result()

對(duì)請(qǐng)求和響應(yīng)添加報(bào)頭,這里設(shè)置的報(bào)頭是長(zhǎng)度,enLength(即添加大小,轉(zhuǎn)化成字符串),也就是封裝了enLength函數(shù):

//"x op y"->"content_len"\r\n"x op y"\r\n
//"exitcode result"->"cotent_len"\r\n"exitcode result"\r\n
const std::string enLength(const std::string &text)
{
    std::string send_string = std::to_string(text.size());
    send_string += LINE_SEP;
    send_string += text;
    send_string += LINE_SEP;
    return send_string;
}

對(duì)請(qǐng)求和響應(yīng)提取報(bào)文,只要報(bào)文,不要報(bào)頭,也就是封裝了deLength函數(shù):

//"cotent_len"\r\n"exitcode result"\r\n
bool deLength(const std::string &package, std::string *text)
{
    auto pos = package.find(LINE_SEP);
    if (pos == std::string::npos)
        return false;
    std::string text_len_string = package.substr(0, pos);
    int text_len = std::stoi(text_len_string);
    *text = package.substr(pos + LINE_SEP_LEN, text_len);
    return true;
}

對(duì)請(qǐng)求和響應(yīng)進(jìn)行序列化和反序列化:對(duì)于序列化和反序列化我們可以用Json來(lái)進(jìn)行實(shí)現(xiàn)

序列化過(guò)程:結(jié)構(gòu)化數(shù)據(jù)->“x op y”

反序列化過(guò)程:“x op y”->結(jié)構(gòu)化數(shù)據(jù)

Protocal.hpp還提供了recvPackage函數(shù)

#define SEP " "
#define SEP_LEN strlen(SEP)
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP)
enum
{
    OK = 0,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERROR
};

//"x op y" --->"content_len"\r\n"x op y"\r\n,添加報(bào)頭
std::string enLength(const std::string &text)
{
    std::string send_string = std::to_string(text.size());
    send_string += LINE_SEP;
    send_string += text;
    send_string += LINE_SEP;
    return send_string;
}

//"content_len"\r\n"exitcode result"\r\n
// 去掉報(bào)頭,得到"exitcode result"
bool deLength(const std::string &package, std::string *text)
{
    auto pos = package.find(LINE_SEP);
    if (pos == std::string::npos)
        return false;
    std::string text_len_string = package.substr(0, pos); // content_len:如“14”
    int text_len = std::stoi(text_len_string);
    *text = package.substr(pos + LINE_SEP_LEN, text_len);
    return true;
}

class Request
{
public:
    Request() : x(0), y(0), op(0)
    {
    }

    Request(int x_, int y_, char op_) : x(x_), y(y_), op(op_)
    {
    }

    // 序列化:
    // 結(jié)構(gòu)化-> "x op y"
    bool serialize(std::string *out)
    {
#ifdef MYSELF
        *out = "";
        std::string x_string = std::to_string(x);
        std::string y_string = std::to_string(y);

        *out = x_string;
        *out += SEP;
        *out += op;
        *out += SEP;
        *out += y_string;
#else
        Json::Value root;
        root["first"] = x;
        root["second"] = y;
        root["oper"] = op;

    Json::FastWriter writer;
    *out = writer.write(root);
#endif
        return true;
    }

    // 反序列化化:
    //"x op y"->結(jié)構(gòu)化
    bool deserialize(const std::string &in)
    {
#ifdef MYSELF
        auto left = in.find(SEP);
        auto right = in.rfind(SEP);
        if (left == std::string::npos || right == std::string::npos)
            return false;
        if (left == right)
            return false;
        if (right - (left + SEP_LEN) != 1)
            return false;
        std::string x_string = in.substr(0, left);
        std::string y_string = in.substr(right + SEP_LEN);

        if (x_string.empty())
            return false;
        if (y_string.empty())
            return false;
        x = std::stoi(x_string);
        y = std::stoi(y_string);
        op = in[left + SEP_LEN];
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        x = root["first"].asInt();
        y = root["second"].asInt();
        op = root["oper"].asInt();
#endif
        return true;
    }

public:
    int x;
    int y;
    char op;
};

class Response
{
public:
    Response() : exitcode(0), result(0)
    {
    }

    Response(int exitcode_, int result_) : exitcode(exitcode_), result(result_)
    {
    }

    bool serialize(std::string *out)
    {
#ifdef MYSELF
        *out = "";
        std::string ec_string = std::to_string(exitcode);
        std::string res_string = std::to_string(result);

        *out = ec_string;
        *out += SEP;
        *out += res_string;
#else
        Json::Value root;
        root["exitcode"] = exitcode;
        root["result"] = result;

        Json::FastWriter writer;
        *out = writer.write(root);
#endif
        return true;
    }

    bool deserialize(const std::string &in)
    {
#ifdef MYSELF
        auto mid = in.find(SEP);
        if (mid == std::string::npos)
            return false;
        std::string ec_string = in.substr(0, mid);
        std::string res_string = in.substr(mid + SEP_LEN);

        if (ec_string.empty() || res_string.empty())
            return false;
        exitcode = std::stoi(ec_string);
        result = std::stoi(res_string);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        exitcode = root["exitcode"].asInt();
        result = root["result"].asInt();
#endif
        return true;
    }

public:
    int exitcode;
    int result;
};

// 讀取報(bào)文,保證讀取的是一個(gè)完整的報(bào)文 ,inbuffer由外部傳入
// "content_len"\r\n"x op y"\r\n"content_len"\r\n"x op y"\r\n"content_len"\r\n"x op
bool recvPackage(int sock, std::string &inbuffer, std::string *text)
{
    char buffer[1024];
    while(true)
    {
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if(n>0)
        {
            buffer[n] = 0;
            inbuffer+=buffer;
            
            auto pos = inbuffer.find(LINE_SEP);
            if(pos == std::string::npos) continue;
            std::string text_len_string = inbuffer.substr(0,pos);
            int text_len  =std::stoi(text_len_string);
            int total_len = text_len_string.size()+2*LINE_SEP_LEN+text_len;

            std::cout<<"處理前#inbuffer:\n"<<inbuffer<<std::endl;
            if(inbuffer.size()< total_len)
            {
                std::cout<<"你輸入的消息,沒(méi)有遵守所定制的協(xié)議,正在等待后續(xù)的內(nèi)容,continue"<<std::endl;
                continue;
            }

            //至少是一個(gè)完整的報(bào)文
            *text = inbuffer.substr(0,total_len);
            inbuffer.erase(0,total_len);

            std::cout<<"處理后#inbuffer:\n"<<inbuffer<<std::endl;
            break;
        }
        else
            return false;
    }
    return true;
}

對(duì)于recvPackage函數(shù)我們要保證讀到的至少是一個(gè)完整的報(bào)文

CalServer

服務(wù)端代碼

//CalServer.hpp
namespace server
{
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };

    static const uint16_t gport = 8080;
    static const int gbacklog = 5;
    typedef std::function<bool(const Request &req, Response &resp)> func_t;


    void handlerEntery(int sock,func_t func)
    {
        std::string inbuffer;
        while(true)
        {
            //1.讀取:"content_len"\r\n"x op y"\r\n
            //保證讀到的消息是一個(gè)完整的請(qǐng)求
            std::string req_text,req_str;
            if(!recvPackage(sock,inbuffer,&req_text)) return;
            std::cout<<"帶報(bào)頭的請(qǐng)求:\n"<<req_text<<std::endl;
            //去掉報(bào)頭
            if(!deLength(req_text,&req_str)) return;
            std::cout<<"去掉報(bào)頭的正文:\n"<<req_str<<std::endl;

            //2.對(duì)請(qǐng)求Request,反序列化
            //2.1得到一個(gè)結(jié)構(gòu)化的請(qǐng)求對(duì)象
            Request req;
            if(!req.deserialize(req_str)) return;

            //3.計(jì)算機(jī)處理————業(yè)務(wù)邏輯
            Response resp;
            func(req,resp);

            //4.對(duì)響應(yīng)Response,進(jìn)行序列化
            //4.1得到一個(gè)"字符串"
            std::string resp_str;
            resp.serialize(&resp_str);

            std::cout<<"計(jì)算完成,序列化響應(yīng):"<<resp_str<<std::endl;

            //5.發(fā)送響應(yīng)
            std::string send_string = enLength(resp_str);
            std::cout<<"構(gòu)建完成完整的響應(yīng)\n"<<send_string<<std::endl;
            send(sock,send_string.c_str(),send_string.size(),0);


        }
    }
    class CalServer
    {
    public:
        CalServer(const uint16_t&port = gport):_listensock(-1),_port(port)
        {}

        void initServer()
        {
            _listensock = socket(AF_INET,SOCK_STREAM,0);
            if(_listensock<0)
            {
                logMessage(FATAL,"create socket error");
                exit(SOCKET_ERR);
            }

            logMessage(NORMAL,"create socket success:%d",_listensock);

            struct sockaddr_in local;
            memset(&local,0,sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;
            if(bind(_listensock,(struct sockaddr*)&local,sizeof(local))<0)
            {
                logMessage(FATAL,"bind socket error");
                exit(BIND_ERR);
            }
            logMessage(NORMAL,"bind socket success");

            if(listen(_listensock,gbacklog)<0)
            {
                logMessage(FATAL,"listen socker error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL,"listen socket success");
        }

        void start(func_t func)
        {
            for(;;)
            {
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                int sock = accept(_listensock,(struct sockaddr*)&peer,&len);
                if(sock<0)
                {
                    logMessage(ERROR,"accept error,next");
                    continue;
                }
                logMessage(NORMAL,"accept a new link success,get new sock:%d",sock);

                pid_t id = fork();
                if(id == 0)
                {
                    close(_listensock);
                    handlerEntery(sock,func);
                    close(sock);
                    exit(0);
                }
                close(sock);

                pid_t ret = waitpid(id,nullptr,0);
                if(ret>0)
                {
                    logMessage(NORMAL,"wait child success");

                }
            }
        }
         ~CalServer() {}
    public:
        int _listensock;
        uint16_t _port;
    };
}

//CalServer.cc
#include "calServer.hpp"
#include <memory>
using namespace server;
using namespace std;
static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}

// req是處理好的完整的請(qǐng)求對(duì)象
// resp:根據(jù)req進(jìn)行業(yè)務(wù)處理,填充resp,不需要管理任何IO,序列化和反序列化
bool cal(const Request &req, Response &resp)
{
    // req已經(jīng)有結(jié)構(gòu)化的數(shù)據(jù)
    resp.exitcode = OK;
    resp.result = 0;
    switch (req.op)
    {
    case '+':
        resp.result = req.x+req.y;
        break;
    case '-':
        resp.result = req.x-req.y;
        break;
    case '*':
        resp.result = req.x*req.y;
        break;
    case '/':
    {
        if(req.y==0) resp.exitcode = DIV_ZERO;
        else resp.result = req.x/req.y;
    }
    break;
    case '%':
    {
        if(req.y == 0)
            resp.exitcode = MOD_ZERO;
        else resp.result = req.x%req.y;
    }
    break;
    default:
        resp.exitcode = OP_ERROR;
        break;
    }
    return true;
}

// tcp服務(wù)器,啟動(dòng)上和udp server一模一樣
// ./tcpserver local_port
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }

    uint16_t port = atoi(argv[1]);
    unique_ptr<CalServer> tsvr(new CalServer(port));
    tsvr->initServer();
    tsvr->start(cal);
    return 0;
}

CalClient

ParseLine:解析,構(gòu)建一個(gè)請(qǐng)求:“1+1”文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-493174.html

#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "Protocol.hpp"
#define NUM 1024

class CalClient
{
public:
    CalClient(const std::string &serverip, const uint16_t &serverport)
        : _sock(-1), _serverip(serverip), _serverport(serverport)
    {
    }
    void initClient()
    {
        // 1. 創(chuàng)建socket
        _sock = socket(AF_INET, SOCK_STREAM, 0);
        if (_sock < 0)
        {
            std::cerr << "socket create error" << std::endl;
            exit(2);
        }
    }
    void start()
    {
        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(_serverport);
        server.sin_addr.s_addr = inet_addr(_serverip.c_str());

        if (connect(_sock, (struct sockaddr *)&server, sizeof(server)) != 0)
        {
            std::cerr << "socket connect error" << std::endl;
        }
        else
        {
            std::string line;
            std::string inbuffer;
            while (true)
            {
                std::cout << "mycal>>> ";
                std::getline(std::cin, line);  // 1+1
                Request req = ParseLine(line); // "1+1"
                std::string content;
                req.serialize(&content);
                std::string send_string = enLength(content);
                send(_sock, send_string.c_str(), send_string.size(), 0); // bug?? 不管

                std::string package, text;
                //  "content_len"\r\n"exitcode result"\r\n
                if (!recvPackage(_sock, inbuffer, &package))
                    continue;
                if (!deLength(package, &text))
                    continue;
                // "exitcode result"
                Response resp;
                resp.deserialize(text);
                std::cout << "exitCode: " << resp.exitcode << std::endl;
                std::cout << "result: " << resp.result << std::endl;
            }
        }
    }
    Request ParseLine(const std::string &line)
    {
        // 建議版本的狀態(tài)機(jī)!
        //"1+1" "123*456" "12/0"
        int status = 0; // 0:操作符之前,1:碰到了操作符 2:操作符之后
        int i = 0;
        int cnt = line.size();
        std::string left, right;
        char op;
        while (i < cnt)
        {
            switch (status)
            {
            case 0:
            {
                if(!isdigit(line[i]))
                {
                    op = line[i];
                    status = 1;
                }
                else left.push_back(line[i++]);
            }
            break;
            case 1:
                i++;
                status = 2;
                break;
            case 2:
                right.push_back(line[i++]);
                break;
            }
        }
        std::cout << std::stoi(left)<<" " << std::stoi(right) << " " << op << std::endl;
        return Request(std::stoi(left), std::stoi(right), op);
    }
    ~CalClient()
    {
        if (_sock >= 0)
            close(_sock);
    }

private:
    int _sock;
    std::string _serverip;
    uint16_t _serverport;
};

#include "calClient.hpp"
#include <memory>

using namespace std;
static void Usage(string proc)
{
    cout<<"\nUasge:\n\t"<<proc<<" serverip serverport\n\n";
}
int main(int argc,char*argv[])
{
    if(argc!=3)
    {
        Usage(argv[0]);
        exit(1);
    }
    string serverip = argv[1];
    uint16_t serverport = atoi(argv[2]);

    unique_ptr<CalClient> tcli(new CalClient(serverip,serverport));
    tcli->initClient();
    tcli->start();
    return 0;
}

Json的安裝

sudo yum install -y jsoncpp-devel

到了這里,關(guān)于【網(wǎng)絡(luò)】協(xié)議的定制與Json序列化和反序列化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • TCP定制協(xié)議,序列化和反序列化

    TCP定制協(xié)議,序列化和反序列化

    目錄 前言 1.理解協(xié)議 2.網(wǎng)絡(luò)版本計(jì)算器 2.1設(shè)計(jì)思路 2.2接口設(shè)計(jì) 2.3代碼實(shí)現(xiàn): 2.4編譯測(cè)試 總結(jié) ? ? ? ? 在之前的文章中,我們說(shuō)TCP是面向字節(jié)流的,但是可能對(duì)于面向字節(jié)流這個(gè)概念,其實(shí)并不理解的,今天我們要介紹的是如何理解TCP是面向字節(jié)流的,通過(guò)編碼的方式,自

    2024年02月12日
    瀏覽(23)
  • 【網(wǎng)絡(luò)編程】協(xié)議定制+Json序列化與反序列化

    【網(wǎng)絡(luò)編程】協(xié)議定制+Json序列化與反序列化

    需要云服務(wù)器等云產(chǎn)品來(lái)學(xué)習(xí)Linux的同學(xué)可以移步/--騰訊云--/--阿里云--/--華為云--/官網(wǎng),輕量型云服務(wù)器低至112元/年,新用戶首次下單享超低折扣。 ? 目錄 一、序列化與反序列化的概念 二、自定義協(xié)議設(shè)計(jì)一個(gè)網(wǎng)絡(luò)計(jì)算器 2.1TCP協(xié)議,如何保證接收方收到了完整的報(bào)文呢?

    2024年02月06日
    瀏覽(25)
  • 協(xié)議定制 + Json序列化反序列化

    協(xié)議定制 + Json序列化反序列化

    1.1 結(jié)構(gòu)化數(shù)據(jù) 協(xié)議是一種 “約定”,socket api的接口, 在讀寫數(shù)據(jù)時(shí),都是按 “字符串” 的方式來(lái)發(fā)送接收的。如果我們要傳輸一些\\\"結(jié)構(gòu)化的數(shù)據(jù)\\\" 怎么辦呢? 結(jié)構(gòu)化數(shù)據(jù): 比如我們?cè)赒Q聊天時(shí),并不是單純地只發(fā)送了消息本身,是把自己的頭像、昵稱、發(fā)送時(shí)間、消息本身

    2024年02月09日
    瀏覽(26)
  • 【網(wǎng)絡(luò)】協(xié)議定制+序列化/反序列化

    【網(wǎng)絡(luò)】協(xié)議定制+序列化/反序列化

    如果光看定義很難理解序列化的意義,那么我們可以從另一個(gè)角度來(lái)推導(dǎo)出什么是序列化, 那么究竟序列化的目的是什么? 其實(shí)序列化最終的目的是為了對(duì)象可以 跨平臺(tái)存儲(chǔ),和進(jìn)行網(wǎng)絡(luò)傳輸 。而我們進(jìn)行跨平臺(tái)存儲(chǔ)和網(wǎng)絡(luò)傳輸?shù)姆绞骄褪荌O,而我們的IO支持的數(shù)據(jù)格式就是

    2024年02月08日
    瀏覽(21)
  • iOS處理json,序列化和反序列化

    Mantle 是一個(gè)開(kāi)源的 Objective-C 框架,用于在 iOS 和 macOS 應(yīng)用程序中實(shí)現(xiàn)模型層的序列化和反序列化。它提供了一種簡(jiǎn)單而強(qiáng)大的方式來(lái)將 JSON數(shù)據(jù)格式轉(zhuǎn)換為自定義的數(shù)據(jù)模型對(duì)象,以及將數(shù)據(jù)模型對(duì)象轉(zhuǎn)換為字典或 JSON 格式。 Mantle具有如下特點(diǎn) 自動(dòng)映射 Mantle自動(dòng)將 JSON 數(shù)據(jù)

    2024年02月11日
    瀏覽(25)
  • rust學(xué)習(xí)-json的序列化和反序列化

    由于 serde 庫(kù)默認(rèn)使用 JSON 格式進(jìn)行序列化和反序列化 因此程序?qū)⑹褂?JSON 格式對(duì)數(shù)據(jù)進(jìn)行序列化和反序列化 JSON:廣泛使用的 JavaScript 對(duì)象符號(hào),用于許多 HTTP API Postcard:no_std 和嵌入式系統(tǒng)友好的緊湊二進(jìn)制格式。 CBOR:用于小消息大小且無(wú)需版本協(xié)商的簡(jiǎn)潔二進(jìn)制對(duì)象表示

    2024年02月12日
    瀏覽(20)
  • ASP.NET中JSON的序列化和反序列化

    ? JSON是專門為瀏覽器中的網(wǎng)頁(yè)上運(yùn)行的JavaScript代碼而設(shè)計(jì)的一種數(shù)據(jù)格式。在網(wǎng)站應(yīng)用中使用JSON的場(chǎng)景越來(lái)越多,本文介紹ASP.NET中JSON的序列化和反序列化,主要對(duì)JSON的簡(jiǎn)單介紹,ASP.NET如何序列化和反序列化的處理,在序列化和反序列化對(duì)日期時(shí)間、集合、字典的處理。

    2024年02月15日
    瀏覽(21)
  • Untiy Json和Xml的序列化和反序列化

    Untiy Json和Xml的序列化和反序列化

    Ps: Unity C# Json 序列化換行 效果: 引用:

    2024年02月13日
    瀏覽(23)
  • 【探索Linux】P.30(序列化和反序列化 | JSON序列化庫(kù) [ C++ ] )

    【探索Linux】P.30(序列化和反序列化 | JSON序列化庫(kù) [ C++ ] )

    當(dāng)談到網(wǎng)絡(luò)編程時(shí),序列化和反序列化是非常重要的概念。在上一篇文章中,我們已經(jīng)了解了在Linux環(huán)境下實(shí)現(xiàn)簡(jiǎn)單的TCP網(wǎng)絡(luò)程序的基礎(chǔ)知識(shí)。本文將繼續(xù)探討序列化和反序列化,這些概念對(duì)于在網(wǎng)絡(luò)上傳輸數(shù)據(jù)以及跨網(wǎng)絡(luò)通信至關(guān)重要。通過(guò)深入了解序列化和反序列化,我

    2024年04月08日
    瀏覽(34)
  • Spring Boot 中使用 ObjectMapper 進(jìn)行 JSON 序列化和反序列化

    在 Java 中,可以使用各種 JSON 序列化和反序列化工具將 Java 對(duì)象轉(zhuǎn)換為 JSON 字符串或者將 JSON 字符串轉(zhuǎn)換為 Java 對(duì)象。其中,Jackson 庫(kù)是比較常用的 JSON 序列化和反序列化工具之一,它提供了 ObjectMapper 類,用于將 Java 對(duì)象轉(zhuǎn)換為 JSON 字符串,或者將 JSON 字符串轉(zhuǎn)換為 Java 對(duì)象

    2024年02月14日
    瀏覽(20)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包