计算机网络(4) --- 协议定制
计算机网络(3) --- 网络套接字TCP_哈里沃克的博客-CSDN博客
https://blog.csdn.net/m0_63488627/article/details/132035757?spm=1001.2014.3001.5501
目录
1. 协议的基础知识
TCP协议通讯流程
编辑
2.协议
1.介绍
2.手写协议
1.内容
2.接口
3.序列化和反序列化
4.协议化
5.读操作
3.客户端和服务端的业务逻辑
1.服务端
2.客户端
1. 协议的基础知识
TCP协议通讯流程
1.不论是三次握手四次挥手还是数据的传输,其实都是操作系统进行执行的。那么两边的函数也只是操作系统的调用接口,操作系统依然是整体的执行者
2.那么我们不能简单的认为accept就是构建链接,因为链接的建立是操作系统提供的,accept更多的是以一种接收管理的姿态。那么三次握手有没有aceept其实不大有关系。
3.链接其实是一种结构体,该结构体是用于存储客户端连接服务器时对客户端的描述,毕竟连接服务端的不一定只有一个客户端,只要客户端多起来,就一定需要被管理,那么aceept的作用就是将接收到的链接进行描述管理
2.协议
1.介绍
1.协议是一种 "约定"。 socket api的接口,之前写的套接字在读写数据时, 都是按 "字节流" 的方式来发送接收的。
2.但是我们需要传输一些"结构化的数据",比如图片,视频之类的东西。设计为了这些功能的实现,我们将这些东西对应的字节流组成一个结构体,那么由该结构体存储,只要我们将这些字节流存储到结构体内,随后进行序列化得到一个字节流,之后传入到网络中去。接收方接收,得到的则是一个字节流,反序列化出结构体再将所有的数据拿出来,这样就实现了所有形式的数据都能被一个报文直接转发过来。
3.同时也要保证接收方收到一个完整的报文。udp不需要考虑,因为它面向数据报的;tcp不同,它是传输字节流的,需要考虑。
2.手写协议
1.内容
1.为了保证接收方收到一个完整的报文,我们需要自己设计报文和报文之间的边界。
2.除了物理层都没有返送和接收的直接连接,应用层的数据想要发送,其实这些数据都在应用层的缓冲区中,而发送的过程,其实是像tcp/ip层进行拷贝,把应用层的缓冲区拷贝到tcp/ip层的发送缓冲区,而另一边的主机则是通过tcp/ip层的接收缓冲区拷贝下层传上来的数据。这些数据最终是通过网络发送的。应用层的函数调用write和read接口都是拷贝函数。那考虑最终结果其实呈现出的是:C的发送缓冲区的数据拷贝到S的接收缓冲区,反之亦然。
3.由于两边都拥有发送和接收缓冲区,那么也就意味着两边同时的传输是不影响的,这种工作模式是全双工的
4.发送数据很多,并且对端不处理这些发送过来的数据,难免出现数据扎堆出现在缓冲区中,那么读取这些数据就想要分离出以一个报文为单位的数据。这种划分有三种方法:定长,定特殊符号或者这自描述方法
2.接口
与read的作用一致,都是把字节流发送出去
与write的作用一致,都是把字节流接收会来
3.序列化和反序列化
#define SEP " " #define SEP_LEN strlen(SEP) // 不要使用sizeof #define LINE_SEP "\r\n" #define LINE_SEP_LEN strlen(LINE_SEP) // 不要使用sizeofclass Request { public:Request(){}Request(int x_, int y_, char op_): x(x_), y(y_), op(op_){}bool serialize(std::string *out){*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;*out += LINE_SEP;}bool deserialize(const std::string &in){auto left = in.find(SEP);auto right = in.find(SEP);if (left == std::string::npos || right == std::string::npos)return false;if (left == right)return false;if (right - (left + SEP_LEN))return false;std::string x_string = in.substr(0, left);if (x_string.empty())return false;std::string y_string = in.substr(right + SEP_LEN);if (y_string.empty())return false;x = std::stoi(x_string);y = std::stoi(y_string);op = in[left + SEP_LEN];return true;}public:int x;int y;char op; };class Response { public:Response(){}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;*out += LINE_SEP;return true;}bool deserialize(const std::string &in){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; };基于计算的业务处理逻辑下:
1.request表示请求,即接收方接收的数据
2.response表示应答,即发送方得到接收方处理结果后的数据
3.不论发送还是接收方,其request和response都是想要有序列化和反序列化的。想要注意的是,序列化和反序列化是一种结构化的类型,不表示协议,它是协议的有效载荷部分
4.序列化的逻辑:将当前存储的一系列想要被操作的数据,通过存储在out中。通过分隔符进行组合
5.反序列化的逻辑:接受到了in,将in的数据拆分回原来的结构,拆分的依据就是分隔符
4.协议化
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; }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; }1.规定的协议为:当前序列化的字节流长度大小作为前面的一个字节流且用\r\n来进行分隔序列化的字节流,大概模式为XXX\r\nYYY\r\n
2.加协议enLength:就是将传入的text之前算出text的大小,先加入大小后填入分隔符最后加入序列化的字节流
3.减协议deLength:先找到第一个分隔符,得到整个序列化字节流的大小,随后通过大小长度收录整个序列化的字节流
5.读操作
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;if (inbuffer.size() < total_len)continue;*text = inbuffer.substr(0, total_len);inbuffer.erase(0, total_len);break;}elsereturn false;}return true; }3.客户端和服务端的业务逻辑
1.服务端
void handerEnter(int sock, func_t func){std::string inbuffer;while (true){// 1.读取// 1.1读取完整的一个报文std::string req_text;if (!recvRequest(sock, inbuffer, &req_text))return;// 1.2读取完整的报文std::string req_str;if (!deLength(req_text, &req_str))return;// 2.反序列化// 2.1得到一个结构化的请求对象Request req;if (!req.deserialize(req_str))return;// 3.计算业务// 3.1得到一个结构化的响应Response resp;func(req, resp);// 4.对响应进行序列化// 4.1得到一个字符串std::string resp_str;resp.serialize(&resp_str);// 5.然会发送给客户端一个响应// 5.1构造新报文std::string send_string = enLength(resp_str);send(sock, send_string.c_str(), send_string.size(), 0);}}2.客户端
void start(){// 5.要发起链接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 << "connect error: " << errno << " : " << strerror(errno) << std::endl;}else{std::string msg;std::string inbuffer;while (true){std::cout << "mycal>>> ";std::getline(std::cin, msg);//msg要拆分Request req(msg);std::string content;req.serialize(&content);std::string send_string = enLength(content);send(_sock, send_string.c_str(), send_string.size(), 0);std::string package, text;if (!recvPackage(_sock, inbuffer, &package))continue;if (!deLength(package, &text))continue;Response resp;resp.deserialize(text);std::cout << "exitcode: " << resp.exitcode << std::endl;std::cout << "result: " << resp.result << std::endl;}}}
相关文章:
计算机网络(4) --- 协议定制
计算机网络(3) --- 网络套接字TCP_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/132035757?spm1001.2014.3001.5501 目录 1. 协议的基础知识 TCP协议通讯流程 编辑 2.协议 1.介绍 2.手写协议 1.内容 2.接口 …...
【Mybatis】Mybatis架构简介
文章目录 1.整体架构图2. 基础支撑层2.1 类型转换模块2.2 日志模块2.3 反射工具模块2.4 Binding 模块2.5 数据源模块2.6缓存模块2.7 解析器模块2.8 事务管理模块 3. 核心处理层3.1 配置解析3.2 SQL 解析与 scripting 模块3.3 SQL 执行3.4 插件 4. 接口层 1.整体架构图 MyBatis…...
如何使用大模型处理生活繁琐的工作
如果每封电子邮件、每个带有订单、发票、投诉、录用请求或工作申请的 PDF 都可以翻译成机器可读的数据,会怎样?然后可以由 ERP / CRM / LMS / TMS 自动处理吗?无需编程特殊接口。 听起来很神奇?它确实有一些魔力。但最近已成为可…...
RpcController作用浅析
RpcController作用浅析 前面提到了RpcConsumer的实现思路,但是并没说明RpcController有什么作用,不妨看看google::protobuf::RpcController: class PROTOBUF_EXPORT RpcController {public:inline RpcController() {}virtual ~RpcControlle…...
Linux(三):Linux服务器下日常实操命令 (常年更新)
基础命令 cd命令:切换目录 cd :切换当前目录百至其它目录,比如进入/etc目录,则执行 cd /etccd / :在Linux 系统中斜杠“/”表示的是根目录。cd / ,即进入根目录.cd ~:进入用户在该系统的home目录&#…...
强大的截图软件--Snipaste
这里写目录标题 前言Snipaste贴图并置顶标注功能 下载 前言 在工作中,我们经常需要保存当前屏幕的图片,虽然系统总是会自带一些截图工具,但似乎用起来总是不那个顺手,例如我们需要对图片进行一些标注,或者将图片贴在屏…...
LeetCode·每日一题·722. 删除注释·模拟
题目 示例 思路 题意 -> 给定一段代码,将代码中的注释删除并返回。 由于注释只有两种类型: 字符串// 表示行注释,表示//和其右侧的其余字符应该被忽略。字符串/* 表示一个块注释,它表示直到下一个(非重叠&#x…...
npm更新和管理已发布的包
目录 1、更改包的可见性 1.1 将公共包设为私有 编辑 使用网站 使用命令行 1.2 将私有包公开 使用网站 使用命令行 2、将协作者添加到用户帐户拥有的私有包 2.1 授予对Web上私有用户包的访问权限 2.2 从命令行界面授予私有包访问权限 2.3 授予对私有组织包的访问权限…...
如何高效使用Gherkin
背景 时间回到2022年,我参与了一个使用了Flutter技术构建的Web前端项目。在这个项目上,我们小组的目标是实施Flutter前端自动化测试。 彼时,Flutter 2.x刚在Web端发力不久,Flutter Web上的应用和生态才刚刚开始,而在…...
[CKA]考试之调度 pod 到指定节点
由于最新的CKA考试改版,不允许存储书签,本博客致力怎么一步步从官网把答案找到,如何修改把题做对,下面开始我们的 CKA之旅 题目为: Task 创建一个Pod,名字为nginx-kusc00401,镜像地址是nginx…...
git 常用命令有哪些
Git 是我们开发工作中使用频率极高的工具,下面总结下他的基本指令有哪些,顺便温习一下。 前言 一般项目中长存2个分支: 主分支(master) 和开发分支(develop) 项目存在三种短期分支 ࿱…...
算法leetcode|66. 加一(rust重拳出击)
文章目录 66. 加一:样例 1:样例 2:样例 3:提示: 分析:题解:rust:go:c:python:java: 66. 加一: 给定一个由 整数 组成的 非…...
MySQL备份Shell脚本
将此脚本添加到crontab计划中,自动留存最新的两份备份 #!/bin/bash # 数据库配置 DB_HOST"localhost" DB_USER"root" DB_PASS"Sxbdc123!#" DB_NAME"ww"# 备份目录 BACKUP_DIR"/opt/mysqlbak"# 备份文件名称 BA…...
Python批量查字典和爬取双语例句
最近,有网友反映,我的批量查字典工具换到其它的网站就不好用了。对此,我想说的是,互联网包罗万象,网站的各种设置也有所不同,并不是所有的在线字典都可以用Python爬取的。事实上,很多网站为了防…...
uni-app、H5实现瀑布流效果封装,列可以自定义
文章目录 前言一、效果二、使用代码三、核心代码总结前言 最近做项目需要实现uni-app、H5实现瀑布流效果封装,网上搜索有很多的例子,但是代码都是不够完整的,下面来封装一个uni-app、H5都能用的代码。在小程序中,一个个item渲染可能出现问题,也通过加锁来解决问题。 一、…...
vue echart3个饼图
概览:根据UI设计需要做3个饼图且之间有关联,并且处理后端返回的数据。 参考链接: echart 官网的一个案例,3个饼图 实现思路: 根据案例,把数据处理成对应的。 参考代码: 1.处理后端数据&am…...
LEARNING TO EXPLORE USING ACTIVE NEURAL SLAM 论文阅读
论文信息 题目:LEARNING TO EXPLORE USING ACTIVE NEURAL SLAM 作者:Devendra Singh Chaplot, Dhiraj Gandhi 项目地址:https://devendrachaplot.github.io/projects/Neural-SLAM 代码地址:https://github.com/devendrachaplot/N…...
item_search-ks-根据关键词取商品列表
一、接口参数说明: item_search-根据关键词取商品列表,点击更多API调试,请移步注册API账号点击获取测试key和secret 公共参数 请求地址: https://api-gw.onebound.cn/ks/item_search 名称类型必须描述keyString是调用key(http:…...
windows运行WPscan报错:无法打开库libcurl.dll
windows运行WPscan报错:无法打开库libcurl.dll 1.问题背景2.解决方案1.问题背景 在Windows上启动WPScan时: wpscan --url xxx.ru提示如下错误: Could not open library libcurl.dll: �� ������ ��������� ������. . Could not open library libcu...
web前端框架Javascript之JavaScript 异步编程史
早期的 Web 应用中,与后台进行交互时,需要进行 form 表单的提交,然后在页面刷新后给用户反馈结果。在页面刷新过程中,后台会重新返回一段 HTML 代码,这段 HTML 中的大部分内容与之前页面基本相同,这势必造成…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...


