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

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

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

目錄

前言

1.理解協(xié)議

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

2.1設(shè)計(jì)思路

2.2接口設(shè)計(jì)

2.3代碼實(shí)現(xiàn):

2.4編譯測試

總結(jié)


前言

? ? ? ? 在之前的文章中,我們說TCP是面向字節(jié)流的,但是可能對于面向字節(jié)流這個概念,其實(shí)并不理解的,今天我們要介紹的是如何理解TCP是面向字節(jié)流的,通過編碼的方式,自己定制協(xié)議,實(shí)現(xiàn)序列化和反序列化,相信看完這篇文章之后,關(guān)于TCP面向字節(jié)流的這個概念,你將會有一個清晰的認(rèn)識,下面我們就一起來看看。

1.理解協(xié)議

? ? ? ? 前面,我們通俗的介紹過協(xié)議,在網(wǎng)絡(luò)中協(xié)議是屬于一種約定,今天要說的是,數(shù)據(jù)在網(wǎng)絡(luò)中傳輸?shù)臅r候,協(xié)議又是如何體現(xiàn)的。

根據(jù)我們之前寫的TCP服務(wù)器實(shí)現(xiàn)數(shù)據(jù)通信知道socket api的接口, 在讀寫數(shù)據(jù)時, 都是按 "字符串" 的方式來發(fā)送接收的. 如果我們要傳輸一些"結(jié)構(gòu)化的數(shù)據(jù)" 怎么辦呢?

什么是結(jié)構(gòu)化的數(shù)據(jù)呢?

舉個簡單的例子,比如在微信上發(fā)送信息的時候,除了有發(fā)送的信息之外還包含有昵稱,時間,頭像這些信息,這些合起來就稱為是結(jié)構(gòu)化的數(shù)據(jù)。

所以我們將結(jié)構(gòu)化的數(shù)據(jù)打包形成一個字符串的過程就稱為是序列化,將打包形成的一個字符串轉(zhuǎn)化為結(jié)構(gòu)化數(shù)據(jù)的過程就稱為是反序列化

如圖所示:

TCP定制協(xié)議,序列化和反序列化,tcp/ip,網(wǎng)絡(luò),java

TCP發(fā)送和接受數(shù)據(jù)的流程

如圖所示:

TCP定制協(xié)議,序列化和反序列化,tcp/ip,網(wǎng)絡(luò),java作為程序員,在應(yīng)用層定義一個緩沖區(qū),然后send接口將數(shù)據(jù)發(fā)送,在這里發(fā)送不是將數(shù)據(jù)直接發(fā)送到網(wǎng)絡(luò)里了,而是調(diào)用send接口將數(shù)據(jù)拷貝到傳輸層操作系統(tǒng)維護(hù)的緩沖區(qū)中,而read是將傳輸層的數(shù)據(jù)拷貝到應(yīng)用層,當(dāng)數(shù)據(jù)拷貝到傳輸層之后,剩下數(shù)據(jù)如何繼續(xù)發(fā)送是由操作系統(tǒng)進(jìn)行維護(hù)的,所以將TCP協(xié)議稱為是傳輸控制協(xié)議,又因?yàn)門CP協(xié)議既可以是客戶端向服務(wù)端發(fā)送信息,也可以是服務(wù)端向客戶端發(fā)送信息,所以TCP是全雙工的。

了解了TCP協(xié)議發(fā)送和接受數(shù)據(jù)的流程之后,因?yàn)門CP是面向字節(jié)流的,思考當(dāng)數(shù)據(jù)由客戶端發(fā)送給服務(wù)端的時候,有沒有可能服務(wù)端的接受緩沖區(qū)中不足一個報(bào)文,有沒有可能上層來不及處理導(dǎo)致服務(wù)端傳輸層接受緩沖區(qū)中有多個報(bào)文的情況,此時如何正確的拿到一個完整的報(bào)文呢?

因?yàn)檫@些問題的存在,所以我們要定制協(xié)議,明確一個完整報(bào)文大小,明確一個報(bào)文和一個報(bào)文的邊界,所以我們要采取定制協(xié)議的方案獲取到一個正確的報(bào)文。

一般采取的策略有三種:

1.定長

2.特殊符號

3.自描述的方式

下面我們按照上述的三種方式實(shí)現(xiàn)編碼上的協(xié)議定制。

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

說明:為了演示協(xié)議定制和序列化以及反序列化在編碼上如何實(shí)現(xiàn),以及如何在編碼上體現(xiàn)TCP面向字節(jié)流的特性,我們通過實(shí)現(xiàn)一個網(wǎng)絡(luò)版本計(jì)算器為大家進(jìn)行介紹

實(shí)現(xiàn)網(wǎng)絡(luò)版本計(jì)算機(jī)約定:

客戶端發(fā)送一個形如"1+1"的字符串;
這個字符串中有兩個操作數(shù), 都是整形;
兩個數(shù)字之間會有一個字符是運(yùn)算符, 運(yùn)算符只能是 + ;
數(shù)字和運(yùn)算符之間沒有空格;

2.1設(shè)計(jì)思路

? ? ? ? 客戶端將想要計(jì)算的請求按照序列化的方式打包成一個字符串,然后發(fā)送給服務(wù)端,服務(wù)端按照定制協(xié)議的方式準(zhǔn)確收到客戶端的請求,然后服務(wù)端進(jìn)行反序列化獲取到結(jié)構(gòu)化的數(shù)據(jù),然后進(jìn)行處理業(yè)務(wù)邏輯計(jì)算結(jié)果,結(jié)果計(jì)算完成之后,服務(wù)端將計(jì)算結(jié)果序列化打包形成一個字符串發(fā)送給客戶端,然后客戶端按照定制協(xié)議的方式準(zhǔn)確獲取到服務(wù)端發(fā)送過來的一個完整報(bào)文,至此就基于TCP協(xié)議實(shí)現(xiàn)了一個網(wǎng)絡(luò)版本的計(jì)算器

2.2接口設(shè)計(jì)

要向完成上述的要求,就必須要包含幾個接口:

a.請求的序列化和反序列化

b.響應(yīng)的序列化和反序列化

c.協(xié)議定制

d.計(jì)算業(yè)務(wù)邏輯

e.準(zhǔn)確獲取一個報(bào)文

f.客戶端和服務(wù)端編寫

2.3代碼實(shí)現(xiàn):

1.請求的序列化和反序列化

class Request
{
public:
    Request()
    :x(0),y(0),op(char()){}
    Request(int x_, int y_, char op_) : x(x_), y(y_), op(op_)
    {}
    bool serialize(std::string *out)
    {
        *out = "";
        // 結(jié)構(gòu)化 -> "x op y";
        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;
        return true;
    }

    // "x op yyyy";
    bool deserialize(const std::string &in)
    {
        // "x op y" -> 結(jié)構(gòu)化
        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); // [0, 2) [start, end) , start, end - start
        std::string y_string = in.substr(right + SEP_LEN);

        if (x_string.empty())
            return false;
        if (y_string.empty())
            return false;
        x = stoi(x_string);
        y = stoi(y_string);
        op = in[left + SEP_LEN];
        return true;
    }

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

序列化結(jié)果:將x,y,op - > 轉(zhuǎn)化為?"x y op\r\n"

反序列化結(jié)果:"x y op\r\n"?- > 轉(zhuǎn)化為?x,y,op

2.響應(yīng)的序列化和反序列化

#define SEP " "
#define SEP_LEN strlen(SEP) // 不敢使用sizeof()
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP) // 不敢使用sizeof()
class Response
{
public:
    Response()
    :exitcode(0),result(0) {}
    Response(int exitcode_, int result_) : exitcode(exitcode_), result(result_)
    {}
    bool serialize(std::string *out)
    {
        *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;
        return true;
    }
    bool deserialize(const std::string &in)
    {
        // "exitcode result"
        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);
        return true;
    }
public:
    int exitcode;
    int result;
};

序列化結(jié)果:將exitcode,result?- > 轉(zhuǎn)化為?"exitcode result\r\n"

反序列化結(jié)果:?"exitcode result\r\n"?- > 轉(zhuǎn)化為?exitcode,result

3.協(xié)議定制

說明:采用自描述的方式+特殊符號,給一個報(bào)文頭部加上報(bào)文的長度,特殊符號"\r\n"用來區(qū)分報(bào)文長度和報(bào)文數(shù)據(jù)

#define SEP " "
#define SEP_LEN strlen(SEP) // 不敢使用sizeof()
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP) // 不敢使用sizeof()
//enLength 和 deLength:打包和解包,解決服務(wù)端和客戶端準(zhǔn)確拿到數(shù)據(jù)
// "x op y" -> "content_len"\r\n"x op y"\r\n
// "exitcode result" -> "content_len"\r\n"exitcode result"\r\n
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
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;
}

4.計(jì)算業(yè)務(wù)邏輯

//req是反序列化后的結(jié)果,根據(jù)res業(yè)務(wù)處理填充req即可
bool cal(const Request& req,Response& res)
{
    //req是結(jié)構(gòu)化的數(shù)據(jù),可以直接使用
    // req已經(jīng)有結(jié)構(gòu)化完成的數(shù)據(jù)啦,你可以直接使用
    res.exitcode = OK;
    res.result = OK;

    switch (req.op)
    {
    case '+':
        res.result = req.x + req.y;
        break;
    case '-':
        res.result = req.x - req.y;
        break;
    case '*':
        res.result = req.x * req.y;
        break;
    case '/':
    {
        if (req.y == 0)
            res.exitcode = DIV_ZERO;
        else
            res.result = req.x / req.y;
    }
    break;
    case '%':
    {
        if (req.y == 0)
            res.exitcode = MOD_ZERO;
        else
            res.result = req.x % req.y;
    }
    break;
    default:
        res.exitcode = OP_ERROR;
        break;
    }

    return true;
}

5.準(zhǔn)確獲取一個報(bào)文

//從sock中讀取數(shù)據(jù)保存到text中
//continue是因?yàn)閠cp協(xié)議是面向字節(jié)流的,傳輸數(shù)據(jù)的時候可能不完整
bool recvPackage(int sock,string &inbuffer,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;
            // text_len_string + "\r\n" + text + "\r\n" <= inbuffer.size();
            std::cout << "處理前#inbuffer: \n" << inbuffer << std::endl;

            if (inbuffer.size() < total_len)
            {
                std::cout << "你輸入的消息,沒有嚴(yán)格遵守我們的協(xié)議,正在等待后續(xù)的內(nèi)容, continue" << std::endl;
                continue;
            }

            // 至少有一個完整的報(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;
}

注:看到這里我們就可以理解了TCP是面向字節(jié)流的概念了。

6.客戶端和服務(wù)端實(shí)現(xiàn):

calServer.hpp:

#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include "log.hpp"
#include "protocol.hpp" //按照協(xié)議約定讀取請求
using namespace std;
namespace server
{
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };
    static const uint16_t gport = 8080;
    static const int gbacklog = 5;
    typedef function<bool(const Request& req,Response& res)> func_t;
    //讀取請求,保證解耦
    void handlerEnter(int sock,func_t fun)
    {
       string inbuffer;
       while(true)
       {
            //1. 讀取:"content_len"\r\n"x op y"\r\n
            // 1.1 你怎么保證你讀到的消息是 【一個】完整的請求
            string req_text, req_str;
            if (!recvPackage(sock,inbuffer,&req_text))
                return;
            std::cout << "帶報(bào)頭的請求:\n" << req_text << std::endl;
            //req_str:獲取報(bào)文
            if (!deLength(req_text, &req_str))
                return;
            std::cout << "去掉報(bào)頭的正文:\n" << req_str << std::endl;
            // 2. 對請求Request,反序列化
            // 2.1 得到一個結(jié)構(gòu)化的請求對象
            Request req;
            if(!req.deserialize(req_str))
                return;
            // 3. 計(jì)算機(jī)處理,req.x, req.op, req.y --- 業(yè)務(wù)邏輯
            // 3.1 得到一個結(jié)構(gòu)化的響應(yīng)
            Response res;
            fun(req,res);//req處理的結(jié)果放到res中,采用回調(diào)的方式保證上層業(yè)務(wù)邏輯和服務(wù)器的解耦
            // 4.對響應(yīng)Response,進(jìn)行序列化
            // 4.1 得到了一個"字符串"
            string resp_str;
            if(!res.serialize(&resp_str))
                return;
             std::cout << "計(jì)算完成, 序列化響應(yīng): " <<  resp_str << std::endl;
            // 5. 然后我們在發(fā)送響應(yīng)
            // 5.1 構(gòu)建成為一個完整的報(bào)文
            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); // 其實(shí)這里的發(fā)送也是有問題的,不過后面再說
       }
    }
    class CalServer
    {
    public:
        CalServer(const uint16_t &port = gport) : _listensock(-1), _port(port)
        {}
        void initServer()
        {
            // 1. 創(chuàng)建socket文件套接字對象
            _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);

            // 2. bind綁定自己的網(wǎng)絡(luò)信息
            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");

            // 3. 設(shè)置socket 為監(jiān)聽狀態(tài)
            if (listen(_listensock, gbacklog) < 0) // 第二個參數(shù)backlog后面在填這個坑
            {
                logMessage(FATAL, "listen socket error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL, "listen socket success");
        }
        void start(func_t fun)
        {
            for (;;)
            {
                // 4. server 獲取新鏈接
                // sock, 和client進(jìn)行通信的fd
                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); // ?

                // version 2 多進(jìn)程版(2)
                pid_t id = fork();
                if (id == 0) // child
                {
                    close(_listensock);
                    handlerEnter(sock,fun);
                    close(sock);
                    exit(0);
                }
                close(sock);

                // father
                pid_t ret = waitpid(id, nullptr, 0);
                if (ret > 0)
                {
                    logMessage(NORMAL, "wait child success"); // ?
                }
            }
        }
        ~CalServer() {}

    private:
        int _listensock; // 不是用來進(jìn)行數(shù)據(jù)通信的,它是用來監(jiān)聽鏈接到來,獲取新鏈接的!
        uint16_t _port;
    };

} // namespace server

calClient.hpp:

#pragma once

#include <iostream>
#include <string>
#include <cstring>
#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;
};

2.4編譯測試

TCP定制協(xié)議,序列化和反序列化,tcp/ip,網(wǎng)絡(luò),java如圖所示:我們準(zhǔn)確的實(shí)現(xiàn)了網(wǎng)絡(luò)版本計(jì)算器

總結(jié)

? ? ? ? 通過上面代碼的編寫,包含定制協(xié)議,序列化和反序列代碼的實(shí)現(xiàn),我們就能夠理解協(xié)議在網(wǎng)絡(luò)傳輸?shù)闹匾粤?,以及理解了TCP是面向字節(jié)流的概念。感謝大家的觀看,希望能夠幫助到大家,我們下次再見。文章來源地址http://www.zghlxwxcb.cn/news/detail-663218.html

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

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

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

相關(guān)文章

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

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

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

    2024年02月06日
    瀏覽(25)
  • 談?wù)刲inux網(wǎng)絡(luò)編程中的應(yīng)用層協(xié)議定制、Json序列化與反序列化那些事

    談?wù)刲inux網(wǎng)絡(luò)編程中的應(yīng)用層協(xié)議定制、Json序列化與反序列化那些事

    由于socket api的接口,在讀寫數(shù)據(jù)的時候是以字符串的方式發(fā)送接收的,如果需要傳輸 結(jié)構(gòu)化的數(shù)據(jù) ,就需要制定一個協(xié)議 結(jié)構(gòu)化數(shù)據(jù)在發(fā)送到網(wǎng)絡(luò)中之前需要完成序列化 接收方收到的是序列字節(jié)流,需要完成反序列化才能使用(如ChatInfo._name) 當(dāng)我們進(jìn)行網(wǎng)絡(luò)通信的的時

    2024年02月06日
    瀏覽(26)
  • 【Linux】應(yīng)用層協(xié)議序列化和反序列化

    【Linux】應(yīng)用層協(xié)議序列化和反序列化

    歡迎來到Cefler的博客?? ??博客主頁:折紙花滿衣 ??個人專欄:題目解析 ??推薦文章:C++【智能指針】 前言 在正式代碼開始前,會有一些前提知識引入 在網(wǎng)絡(luò)應(yīng)用層中,序列化(Serialization)和反序列化(Deserialization)是將數(shù)據(jù)轉(zhuǎn)換為可在網(wǎng)絡(luò)上傳輸?shù)母袷?,并從網(wǎng)絡(luò)接

    2024年04月23日
    瀏覽(46)
  • [計(jì)算機(jī)網(wǎng)絡(luò)]---序列化和反序列化

    [計(jì)算機(jī)網(wǎng)絡(luò)]---序列化和反序列化

    前言 作者 :小蝸牛向前沖 名言 :我可以接受失敗,但我不能接受放棄 ?? 如果覺的博主的文章還不錯的話,還請 點(diǎn)贊,收藏,關(guān)注??支持博主。如果發(fā)現(xiàn)有問題的地方歡迎?大家在評論區(qū)指正? 目錄 ?一、再談協(xié)議 二、序列化和反序化 1、網(wǎng)絡(luò)版本計(jì)算器的場景搭建 2、

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

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

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

    2024年02月09日
    瀏覽(26)
  • 網(wǎng)絡(luò)數(shù)據(jù)通信—ProtoBuf實(shí)現(xiàn)序列化和反序列化

    目錄 前言 1.環(huán)境搭建 2. centos下編寫的注意事項(xiàng) 3.約定雙端交互接口 4.約定雙端交互req/resp 5. 客戶端代碼實(shí)現(xiàn) 6.服務(wù)端代碼實(shí)現(xiàn) Protobuf還常用于通訊協(xié)議、服務(wù)端數(shù)據(jù)交換場景。那么在這個示例中,我們將實(shí)現(xiàn)一個網(wǎng)絡(luò)版本的通訊錄,模擬實(shí)現(xiàn)客戶端與服務(wù)端的交互,通過P

    2024年02月04日
    瀏覽(18)
  • 【Linux后端服務(wù)器開發(fā)】協(xié)議定制(序列化與反序列化)

    【Linux后端服務(wù)器開發(fā)】協(xié)議定制(序列化與反序列化)

    目錄 一、應(yīng)用層協(xié)議概述 二、序列化與反序列化 Protocal.h頭文件 Server.h頭文件 Client.h頭文件 server.cpp源文件 client.cpp源文件 什么是應(yīng)用層 ?我們通過編寫程序解決一個個實(shí)際問題、滿足我們?nèi)粘P枨蟮木W(wǎng)絡(luò)程序,都是應(yīng)用層程序。 協(xié)議是一種“約定”,socket的api接口,在讀

    2024年02月16日
    瀏覽(21)
  • Go語言網(wǎng)絡(luò)編程入門:TCP、HTTP、JSON序列化、Gin、WebSocket、RPC、gRPC示例

    Go語言網(wǎng)絡(luò)編程入門:TCP、HTTP、JSON序列化、Gin、WebSocket、RPC、gRPC示例

    在本文中,我們將介紹Go語言中的網(wǎng)絡(luò)編程的不同方式,包括TCP、HTTP、Gin框架、WebSocket、RPC、gRPC的介紹與連接實(shí)例,并對所有示例代碼都給出了詳細(xì)的注釋,最后對每種模式進(jìn)行了總結(jié)。 TCP(傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,提供

    2024年02月16日
    瀏覽(28)
  • 【Linux】序列化和反序列化

    【Linux】序列化和反序列化

    在網(wǎng)絡(luò)編程中,直接使用 結(jié)構(gòu)體 進(jìn)行數(shù)據(jù)傳輸會出錯,因?yàn)?本質(zhì)上socket無法傳輸結(jié)構(gòu)體 ,我們只有將結(jié)構(gòu)體裝換為字節(jié)數(shù)組,或者是字符串格式來傳輸,然后對端主機(jī)收到了數(shù)據(jù),再將其轉(zhuǎn)化為結(jié)構(gòu)體,這就是序列化和反序列化的過程! 序列化 (Serialization)是將對象的狀態(tài)

    2024年02月10日
    瀏覽(19)
  • 什么是序列化和反序列化?

    JSON(JavaScript Object Notation)和XML(eXtensible Markup Language)是兩種常用的數(shù)據(jù)交換格式,用于在不同系統(tǒng)之間傳輸和存儲數(shù)據(jù)。 JSON是一種輕量級的數(shù)據(jù)交換格式,它使用易于理解的鍵值對的形式表示數(shù)據(jù)。JSON數(shù)據(jù)結(jié)構(gòu)簡單明了,易于讀寫和解析,是基于JavaScript的一種常用數(shù)據(jù)

    2024年02月09日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包