【计算机网络】协议定制

一、结构化数据传输流程

这里涉及协议定制序列化/反序列化的知识

对于序列化和反序列化,有现成的解决方案:①json ②probuff ③xml

二、理解发送接收函数

我们调用的所有发送/接收函数,根本就不是把数据发送到网络中!本质都是拷贝函数!

Client -> Server:tcp发送的本质,就是将数据从c的发送缓冲区,拷贝到s的接收缓冲区!

Client -> Server:tcp发送的本质,就是将数据从c的发送缓冲区,拷贝到s的接收缓冲区!

每一端都有一套发送缓冲区/接收缓冲区 -> tcp是全双工的!

三、网络计算器流程

分析网络计算器的流程,就可以理解协议定制序列化/反序列化协议报头的作用了

说明:这里只谈论整体框架,不会细说每个函数的实现,想要完整代码的可以参考下面链接!

https://gitee.com/peter-chen-cs/linux_learning_code.git

1.定制协议

cpp 复制代码
#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>

// 添加报头
std::string enLength(const std::string &text)
// 去掉报头
bool deLength(const std::string &package, std::string *text)

// 请求
class Request
{
public:
    // 构造函数
    Request()
    // 序列化
    bool serialize(std::string *out)
    // 反序列化
    bool deserialize(const std::string &in)

public:
    int _x;
    int _y;
    char _op; // "_x _op _y"
};

// 响应
class Response
{
public:
    // 构造函数
    Response()
    // 序列化
    bool serialize(std::string *out)
    // 反序列化
    bool deserialize(const std::string &in)

public:
    int _exitcode; // 0表示计算成功;!0表示计算失败
    int _result;   // 计算结果
};

// 功能:保证读到的数据是一个完整的报文
bool recvPackage(int sock, std::string &inbuffer, std::string *text)

2.服务端

(1)calServer.hpp

cpp 复制代码
// 计算服务器-用于计算
class CalServer
{
public:
    // 构造函数
    CalServer()
    // 析构函数
    ~CalServer(){}
    // 初始化计算服务器
    void initServer()
    // 启动计算服务器
    void start(func_t func)
    {...handlerEntery(){func_t func()}...}

private:
    int _listensock;
    uint16_t _port;
};

typedef std::function<bool(const Request &req, Response &resp)> func_t; // 处理业务 

// 放在这里是为了保证解耦
void handlerEntery(int sock, func_t func)
{
    while (true)
    {
        // 1.从应用层缓冲区读取一个完整报文
        // 2.对请求Request反序列化-得到一个结构化的请求对象
        // 3.计算处理 -- 逻辑业务:得到一个结构化响应
        func(req, resp);
        // 4.对响应Response进行序列化-得到一个"字符串"
        // 5.添加包头,发送响应
    }
}

(2)calServer.cpp

cpp 复制代码
#include "calServer.hpp"
#include <memory>

bool cal(const Request &req, Response &resp)
{
    // 请求已经是结构化数据了,可以直接使用
    // 根据结构化请求完成计算
    // 构建结构化的响应
}


int main(int argc, char *argv[])
{
    // 启动服务器
    unique_ptr<CalServer> tsvr(new CalServer(port));
    tsvr->initServer();
    tsvr->start(cal);
    return 0;
}

3.客户端

(1)calClient.hpp

cpp 复制代码
class CalClient
{
public:
    // 构造函数
    CalClient(const std::string &serverip, const uint16_t &serverport)
    // 析构函数
    ~CalClient(){}
    // 初始化客户端
    void initClient()
    // 启动服务端
    void start()
    {
        // 建立连接
        while (true)
        {
            // 输入算式,并将输入的字符串转化成Request-ParseLine()
            // 将Request序列化
            // 添加报头
            // 发送到服务器

            // --服务器处理完发回来了--

            // 读取一个完整的响应
            // 去掉报头
            // 反序列化得到Response
        }
    }

    // 把从键盘输入的算式转化成一个Request请求
    Request ParseLine(const std::string &line)

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

(2)calClient.cpp

cpp 复制代码
#include "calClient.hpp"
#include <memory>

int main(int argc, char *argv[])
{
    // 启动客户端
}

4.整体调用逻辑

相关推荐
天上掉下来个程小白7 分钟前
案例-14.文件上传-简介
数据库·spring boot·后端·mybatis·状态模式
风与沙的较量丶23 分钟前
Java中的局部变量和成员变量在内存中的位置
java·开发语言
水煮庄周鱼鱼30 分钟前
C# 入门简介
开发语言·c#
澄澈天空34 分钟前
C++ MFC添加RichEditControl控件后,程序启动失败
c++·mfc
Asthenia04121 小时前
基于Jackson注解的JSON工具封装与Redis集成实战
后端
编程星空1 小时前
css主题色修改后会多出一个css吗?css怎么定义变量?
开发语言·后端·rust
shimly1234561 小时前
tcpdump 用法示例
网络·测试工具·tcpdump
软件黑马王子1 小时前
Unity游戏制作中的C#基础(6)方法和类的知识点深度剖析
开发语言·游戏·unity·c#
Lzc7741 小时前
C++初阶——简单实现vector
c++·简单实现vector
风静如云1 小时前
OpenBMC:BmcWeb定义service
linux