网络基础二
文章目录
- 协议定制,序列化和反序列化
- 应用层
- 网络版计算器
- 协议的定制
- 序列反序列化
- 序列化
- 未复用版
- 反序列化
TCP是面向字节流的,你怎么保证,你读取上来的数据,是‘’一个“ “完整””的报文呢?

我们没有区分字符串里面有什么内容,连字符串都没有区分,我给你发了个你好,服务器这里read就一定能读到个你好 吗?
对方发过来因为网络问题只发过来一个你而已,但是之前并没有这个问题啊,那是因为网络好,数据量也不大。
就像之前管道写了好几次,但是读端把数据一下子全读上来了。
为什么觉得文件操作恶心,文件部分也和协议有关。
比如我把数据写到文件里,可能连续写了十几条消息,写好写,可是读的时候,里面有字符串有整数,当我读取时比较困难的把数据反向转换回来,且读的时候可能人家写了十几次我要读我调用一个fread把整个文件全都读进来了,此时你怎么保证你读上来的就是一个完整的拿到一段你想要的数据呢?
这个其实比较困难,因为这里有知识的残缺,必须解决。
那我按行读取不就完了吗,按行读取仅仅是对文件一种读取方式,那我一大堆二进制数据,你怎么保证读上来了关键字段呢?
正确对文件读写,对管道读写,对网络读写,尤其是面向字节流,你怎么保证你读上来的是一个完整的报文呢?
则今天服务器的read是有BUG的。
我们今天拷贝字符串从C到S,可是服务器就是从接受缓冲区里读,造成接受缓冲区快被打满了,此时客户端发数据可能只发了一部分这种情况
作为用户只需要在应用层通过write把数据拷贝到TCP发送缓冲区里,write调用直接返回,这个函数调用完了,可是这个数据不一定已经发给对方接受缓冲区!
数据不一定发送到网络里,所以write ,read,send , recv这样的接口不叫网络收发,实际上他的作用就是用户到内核拷贝,而真正决定网络收发的协议是由TCP协议决定的,因为只有TCP协议比较了解网络当前的健康状态和接收方的接受能力,所以必须由TCP全权负责:
1.什么时候发?
2.发多少?
3.出错了怎么办?
TCP协议是不是在OS内部实现的?
属于OS编译好的一部分。
所以OS属于内核,你所谓的用户把数据交给TCP这句话有点不太可信,实际上是用户把自己的数据交给了OS了,那你放心OS吗,当年讲文件操作时,其实是把用户的数据拷贝到文件的缓冲区里,最后由OS来把文件缓冲区的数据定期刷新到磁盘,如果你不相信OS,为什么当年你要相信呢?
所以用户把数据交给TCP,是用户把自己的数据交给了OS!
所以文件操作叫log.tx,今天的文件就叫做TCP。
此时把数据从用户层拷贝到内核你就别管了,作为用户直接返回就行了,OS会决定定期发多少。
发送谈完了再来谈谈接受,这时候就有点搞笑了,怎么搞笑呢?
作为接收方来讲,他要通过read调用,说白了是把接受缓冲区的数据拷贝到用户层缓冲区buffer[]
所以对方给我发了多少数据,什么时候发的,有没有把完整的数据一次全打包还是分三份打包过来?
接受缓冲区接受到的数据完全由OS决定了,对方发的时候可能把整个字符串分了三份发过来,也可能整体打包发过来,甚至把发了三四次写的数据最后打包整体发过来了。
假设读的时候一次全读完,有时候还读不完。
假设把缓冲区一次全读完,到底把数据有没有读到在应用层是一个我所认识的完整的报文,是一个字符串的一部分,还是读上来三四个报文,我们这里就完全不确定了,所以要对读上来数据进行更细节的分析。
所以在应用层我们要清楚,我们就必须得保证在应用层把协议定好,我们才能更好的进行读上来的数据的分析。
协议定制,序列化和反序列化
我规定好通信双方使用固定大小的报文,比如发送端是64字节,我在read返回值小于64字节,这个报文就不完整,我就把报文继续维持起来,当我下次继续读的时候一定要凑够64字节然后进行处理。
相当于把文件固定大小每次写一行,读也读一行,也叫订协议。
应用层
网络版计算器
方案一
发送“1+1”字符串,然后以类似方式返回
这样不太好,如果一下发了三四个请求,该如何区分呢?
方案二
定义请求结构体,直接把结构体大小字节的二进制数据发给对方,对方使用同样类型的结构体就可以提取出整数 a和整数 b,结果也是结构体处理
通信双发不发字符串,直接发对象,可以吗?
这是肯定可以的。但是在应用层不建议。
问题
- 同一个结构体先后在不同的编译器下编译出来的同一个结构体的大小一定是一样吗?
在内核层这样搞没问题,因为不管Windows还是Linux你们用的协议都叫TCP/IP协议。
可是用户应用层的编译器就千差万别了,编译出来的大小可能就是不一样的,因为有结构体对齐,他按8,他按4,大小就不一样。
比如说网络带宽特别差,接收方接受缓冲区已经被打满了,接收方给发送方说我来不及接收了先别发,所以TCP发送方就不发了,可是用户不知道,他就一直拷到TCP发送缓冲区里,四五个报文全在TCP缓冲区里,后来接收方说我好了你发吧, 我可以接受很大数据,TCP把四五个请求全给他发过去了,四五个请求是纯二进制的,那你怎么去区分一个一个报文呢?
我们该如何设计网络版本计算器的协议?
协议 = 结构体
整个结构体当中每一个结构体每一个字段都要让客户端和服务端约定好的。
约定好之后使用结构化的方式把约定表达出来,这就叫做定义出来了协议。
协议的定制
我们在微信聊天的时候约定通用结构体,这就叫定了聊天协议。
序列反序列化
我们在网络通信的时候,整个结构化的数据把多个字符串转化成一个字符串,这个过程称之为序列化。
把一个字符串打散成多个字符串转换成结构体化数据,叫做反序列化
我们最终为什么要序列反序列化呢?主要是序列反序列化之后方便网络进行收和发。
那发过去的一个大字符串,收过来一个字符串,我怎么保证把字符串收全呢?
后面还要设计报文和报文之间的分隔符。
所以方案一和方案二我们两个都用了。
不把多字符串整个成一个,那一个一个发,昵称啊,内容啊,时间啊,对端还要把多个字符串关联起来,难度太大。
我们要把创建套接字,绑定,监听,accept,connect全部封装成一个类Sock,不然写到Tcpserver类里面就很混乱。
这样Tcpserver调用起来逻辑很清晰。
客户端同理
让客户端和服务器双方使用同一套接口就行,不用来回写车轱辘代码了。
从此往后我们再也不写套接字了,因为我们有了小组件Socket.hpp的类Sock
前面说了要定制协议,就是设计Request和Response结构体,再把结构化的数据序列化成一个大字符串
我们的请求计算器可以从
int x int y char op
变为 字符串 “x op y”
接受缓冲区收到这种风格的字符串,也能解析,可是对方发来了多个这样的字符串,上层通过调用read();读取字符串的时候,他怎么保证上层读上来的是一个完整的报文呢?
有没有他读上来的是半个,一个半,两个。
如果你读上来的是两个,你怎么把这两个区分开?
如果你读上来的是一个半,你怎么证明一个半当中,哪一个是当前的,哪一个是下一个。
如果读上来是半个呢,你怎么知道报文多长呢?
请求和请求之间用特殊符号把他们分隔开
当上层读的时候碰到\n字符,\n之前的所有字符全部都收到了,就可做到报文和报文之间隔开了。
假设把缓冲区全部读上来,之后的问题就是字符串分析
把整个报文用\n分开,左边一个报文,右边一个报文。
不一定非得用\n,你可以用\3或者绝不会在报文中出现的分隔符
计算器场景比较简单,用\n分割一个个报文,这样我们再做字符串分析绝对可以分出一个一个子串,然后再对子串切割绝对能恢复成结构体
这样做有点简单,另一方面还是不够完善,因为有可能读上来的字符根本不是你想的那样,如果缓冲区只有半个报文呢,你怎么保证你读上来的是一个完整的报文呢?
有人说我只要判断有没有\n就可以了,没毛病,这样肯定可以的,不过今天我还想加一个东西,我想在报文前再加一个字段,长度
这个长度字段可以固定大小,也可以是字符串
这个长度是整个完整报文的长度是多少,这个长度不包括\n
我们还可以添加一个协议类型报头,让计算器支持浮点数或者整形计算。
今天就不这么复杂带这个协议类型了
最终的报文字符串风格就是这样子
将来读取的这一方,他可以一直读到\n,就可以把第一个字段读上来,也就是读到了第一个报文的长度。
也可以把全部缓冲区的报文都读上来,读上来之后根据第一个\n分析清楚是9,就知道第一个报文的长度,从第一个\n往后连续读取9个字符,我就能保证读到了一个完整的报文了。
100 + 200 \n这个\n一会再说。
后续字符串同理处理。
有人说200 后面的\n 要不要其实都无所谓了,因为已经有长度了,为什么还要带呢?今天把他带上未来想调试的话printf cout 直接打出来就会变成如下的样子。
很直观就能看到协议定制效果。
序列化
未复用版
请求“len\nx op y" y后面的\n其他地方加
反序列化
我们除了要解决一个报文内部的问题,这是序列化和反序列化
我们还要解决报文和报文之间的问题
课上代码因为在序列化过程中无论是客户端还是服务端都需要封装报头长度,外加最后的\n,所以不如在设置Encode来复用,他们两个都可以加报头和尾部\n
Encode
对"x op y" 添加报头长度\n 和 尾部\n
Decode函数
从len"\n"x op y"\n提取有效报文 “x op y”
内部
1.查找第一个\n,如果没找到直接返回,说明长度报头没有,就不玩了。
2.整个报文的长度应该是len(x op y的长度)+len长度报头本身的长度+2 (两个\n)
对要Decode的len"\n"x op y"\n…进行长度检查,如果整个读上来的报文长度不够说明这不是一个完整的报文请求,我也不玩了。
3.利用substr切出有效报文的子串
4.从package大长字符串移除此报文
一 把网络功能写出来
二 协议定好
三 把这俩货捏在一起 servercal.hpp Tcpserver
在tcpserver类中设置回调函数, 涉及了bind,bind的是calculato函数
相关文章:

网络基础二
文章目录 协议定制,序列化和反序列化应用层网络版计算器协议的定制序列反序列化序列化未复用版 反序列化 TCP是面向字节流的,你怎么保证,你读取上来的数据,是‘’一个“ “完整””的报文呢? 我们没有区分字符串里面有…...

从Full-Text Search全文检索到RAG检索增强
从Full-Text Search全文检索到RAG检索增强 时光飞逝,转眼间六年过去了,六年前铁蛋优化单表千万级数据查询性能的场景依然历历在目,铁蛋也从最开始做CRUD转行去了大数据平台开发,混迹包装开源的业务,机缘巧合下做了实时…...

springMVC 全局异常统一处理
全局异常处理⽅式⼀: 1、配置简单异常处理器 配置 SimpleMappingExceptionResolver 对象: <!-- 配置全局异常统⼀处理的 Bean (简单异常处理器) --> <bean class"org.springframework.web.servlet.handler.SimpleMappingExceptionReso…...

qt ubuntu i386 系统
sudo ln -s cmake-3.31.0-linux-x86_64/bin/* /usr/local/bin 【Ubuntu20.4安装QT6 - CSDN App】Ubuntu20.4安装QT6_ubuntu安装qt6-CSDN博客 sudo ../configure -release -platform linux-g-64 -static -nomake examples -nomake demos -no-qt3support -no-script -no-scriptt…...

BUUCTF—Reverse—helloword(6)
一道安卓逆向的签到题 下载附件 使用JADX-gui反编译工具打开(注意配环境),找到主函数 jadx 本身就是一个开源项目,源代码已经在 Github 上开源了 官方地址:GitHub - skylot/jadx: Dex to Java decompiler 发现flag …...

深入解析下oracle date底层存储方式
之前我们介绍了varchar2和char的数据库底层存储格式,今天我们介绍下date类型的数据存储格式,并通过测试程序快速获取一个日期。 一、环境搭建 1.1,创建表 我们还是创建一个测试表t_code,并插入数据: 1.2,…...

Elasticsearch 开放推理 API 增加了对 IBM watsonx.ai Slate 嵌入模型的支持
作者:来自 Elastic Saikat Sarkar 使用 Elasticsearch 向量数据库构建搜索 AI 体验时如何使用 IBM watsonx™ Slate 文本嵌入。 Elastic 很高兴地宣布,通过集成 IBM watsonx™ Slate 嵌入模型,我们的开放推理 API 功能得以扩展,这…...

如何搭建一个小程序:从零开始的详细指南
在当今数字化时代,小程序以其轻便、无需下载安装即可使用的特点,成为了连接用户与服务的重要桥梁。无论是零售、餐饮、教育还是娱乐行业,小程序都展现了巨大的潜力。如果你正考虑搭建一个小程序,本文将为你提供一个从零开始的详细…...

NFS搭建
NFS搭建 单节点安装配置服务器安装配置启动并使NFS服务开机自启客户端挂载查看是否能发现服务器的共享文件夹创建挂载目录临时挂载自动挂载 双节点安装配置服务器安装配置服务端配置NFS服务端配置Keepalived编辑nfs_check.sh监控脚本安装部署RsyncInofity 客户端 单节点安装配置…...

RNN与LSTM,通过Tensorflow在手写体识别上实战
简介:本文从RNN与LSTM的原理讲起,在手写体识别上进行代码实战。同时列举了优化思路与优化结果,都是基于Tensorflow1.14.0的环境下,希望能给您的神经网络学习带来一定的帮助。如果您觉得我讲的还行,希望可以得到您的点赞…...

Docker部署FastAPI实战
在现代 Web 开发领域,FastAPI 作为一款高性能的 Python 框架,正逐渐崭露头角,它凭借简洁的语法、快速的执行速度以及出色的类型提示功能,深受开发者的喜爱。而 Docker 容器化技术则为 FastAPI 应用的部署提供了便捷、高效且可移植…...

【Python数据分析五十个小案例】电影评分分析:使用Pandas分析电影评分数据,探索评分的分布、热门电影、用户偏好
博客主页:小馒头学python 本文专栏: Python数据分析五十个小案例 专栏简介:分享五十个Python数据分析小案例 在现代电影行业中,数据分析已经成为提升用户体验和电影推荐的关键工具。通过分析电影评分数据,我们可以揭示出用户的…...

Vue2学习记录
前言 这篇笔记,是根据B站尚硅谷的Vue2网课学习整理的,用来学习的 如果有错误,还请大佬指正 Vue核心 Vue简介 Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。 它基于标准 HTML、CSS 和 JavaScr…...

TMS FNC UI Pack 5.4.0 for Delphi 12
TMS FNC UI Pack是适用于 Delphi 和 C Builder 的多功能 UI 控件的综合集合,提供跨 VCL、FMX、LCL 和 TMS WEB Core 等平台的强大功能。这个统一的组件集包括基本工具,如网格、规划器、树视图、功能区和丰富的编辑器,确保兼容性和简化的开发。…...

Redis主从架构
Redis(Remote Dictionary Server)是一个开源的、高性能的键值对存储系统,广泛应用于缓存、消息队列、实时分析等场景。为了提高系统的可用性、可靠性和读写性能,Redis提供了主从复制(Master-Slave Replication…...

logback动态获取nacos配置
文章目录 前言一、整体思路二、使用bootstrap.yml三、增加环境变量四、pom文件五、logback-spring.xml更改总结 前言 主要是logback动态获取nacos的配置信息,结尾完整代码 项目springcloudnacosplumelog,使用的时候、特别是部署的时候,需要改环境&#…...

KETTLE安装部署V2.0
一、前置准备工作 JDK:下载JDK (1.8),安装并配置 JAVA_HOME 环境变量,并将其下的 bin 目录追加到 PATH 环境变量中。如果你的环境中已存在,可以跳过这步。KETTLE(8.2)压缩包:LHR提供关闭防火墙…...

[RabbitMQ] 保证消息可靠性的三大机制------消息确认,持久化,发送方确认
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...

aws服务--机密数据存储AWS Secrets Manager(1)介绍和使用
一、介绍 1、简介 AWS Secrets Manager 是一个完全托管的服务,用于保护应用程序、服务和 IT 资源中的机密信息。它支持安全地存储、管理和访问应用程序所需的机密数据,比如数据库凭证、API 密钥、访问密钥等。通过 Secrets Manager,你可以轻松管理、轮换和访问这些机密信息…...

Java设计模式笔记(一)
Java设计模式笔记(一) (23种设计模式由于篇幅较大分为两篇展示) 一、设计模式介绍 1、设计模式的目的 让程序具有更好的: 代码重用性可读性可扩展性可靠性高内聚,低耦合 2、设计模式的七大原则 单一职…...

Unity3d C# 实现一个基于UGUI的自适应尺寸图片查看器(含源码)
前言 Unity3d实现的数字沙盘系统中,总有一些图片或者图片列表需要点击后弹窗显示大图,这个弹窗在不同尺寸分辨率的图片查看处理起来比较麻烦,所以,需要图片能够根据容器的大小自适应地进行缩放,兼容不太尺寸下的横竖图…...

【es6进阶】vue3中的数据劫持的最新实现方案的proxy的详解
vuejs中实现数据的劫持,v2中使用的是Object.defineProperty()来实现的,在大版本v3中彻底重写了这部分,使用了proxy这个数据代理的方式,来修复了v2中对数组和对象的劫持的遗留问题。 proxy是什么 Proxy 用于修改某些操作的默认行为࿰…...

w~视觉~3D~合集3
我自己的原文哦~ https://blog.51cto.com/whaosoft/12538137 #SIF3D 通过两种创新的注意力机制——三元意图感知注意力(TIA)和场景语义一致性感知注意力(SCA)——来识别场景中的显著点云,并辅助运动轨迹和姿态的预测…...

IT服务团队建设与管理
在 IT 服务团队中,需要明确各种角色。例如系统管理员负责服务器和网络设备的维护与管理;软件工程师专注于软件的开发、测试和维护;运维工程师则保障系统的稳定运行,包括监控、故障排除等。通过清晰地定义每个角色的职责࿰…...

一文学习开源框架OkHttp
OkHttp 是一个开源项目。它由 Square 开发并维护,是一个现代化、功能强大的网络请求库,主要用于与 RESTful API 交互或执行网络通信操作。它是 Android 和 Java 开发中非常流行的 HTTP 客户端,具有高效、可靠、可扩展的特点。 核心特点 高效…...

自研芯片逾十年,亚马逊云科技Graviton系列芯片全面成熟
在云厂商自研芯片的浪潮中,亚马逊云科技无疑是最早践行这一趋势的先驱。自其迈出自研芯片的第一步起,便如同一颗石子投入平静的湖面,激起了层层涟漪,引领着云服务和云上算力向着更高性能、更低成本的方向演进。 早在2012年&#x…...

Stable Diffusion 3 部署笔记
SD3下载地址:https://huggingface.co/stabilityai/stable-diffusion-3-medium/tree/main https://huggingface.co/spaces/stabilityai/stable-diffusion-3-medium comfyui 教程: 深度测评:SD3模型表现如何?实用教程助你玩转Stabl…...

微信小程序WXSS全局样式与局部样式的使用教程
微信小程序WXSS全局样式与局部样式的使用教程 引言 在微信小程序的开发中,样式的设计与实现是提升用户体验的关键部分。WXSS(WeiXin Style Sheets)作为微信小程序的样式表语言,不仅支持丰富的样式功能,还能通过全局样式与局部样式的灵活运用,帮助开发者构建美观且易于维…...

Docker 部署 MongoDB
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🍃 vue-uniapp-template 🌺 仓库主页: GitCode💫 Gitee …...

Unity图形学之法线贴图原理
1.正常贴图:RGBA 4通道 每个通道取值范围 0-255 贴图里面取值是 0-1 2.法线贴图:法线怎么存入正常贴图的过程 每个通道里面存储的是一个向量(x,y,z,w) 通常我们会对应xyzw为rgba 存储值的范围也是0-1向量的取值范围是 -1到1法线怎么存入正常贴图的过程&…...