当前位置: 首页 > news >正文

【计算机网络】应用层自定义协议与序列化

记得在上一节我们说过TCP中的读取时需要改进,这节就可以解决读取问题了。

目录

  • 应用层
    • 再谈 "协议"
    • 网络版计算机
      • 方案一
      • 方案二
    • 序列化 和 反序列化
  • 重新理解 read、write、recv、send 和 tcp 为什么支持全双工

应用层

再谈 “协议”

我们在UDP与TCP中写的代码都是在应用层的,而协议栈每层都有协议,但是似乎没见到我们写的代码有协议?
实际上我们也定了协议,那就是都是字符串。

网络版计算机

但是更多的时候协议是结构体,而不是字符串。
但是如果是结构体,又该怎么样去进行网络传输?

方案一

这是肯定就有人说,和字符串一样直接传过去不就好了?这确实是一种解决办法。
我们的OS内部甚至就是这种方案,但是应用层并不推荐。

原因有二:技术与业务

技术方面:当我们在服务端在64位 Linux下,而客户端在Macos、win…
不用的OS大小端、内存对齐规则、字段大小都不一致的,所以这是第一方面的难题,直接使用结构体传是肯定难以实现的!
业务方面:就算有同学头铁,两眼一睁就是干,就是解决了技术方面问题,那算你牛。但是业务是一直会变化的,所以业务变化就会导致你的技术方面工作全部白费,因此应用层不推荐这么做。

而OS可以这么做的原因就在于写好了他就是万年不变的了,都是使用C语言写的,保证效率即可。

方案二

  • 定义结构体来表示我们需要交互的信息;
  • 发送数据时将这个结构体按照一个规则转换成字符串, 接收到数据的时候再按
    照相同的规则把字符串转化回结构体;
  • 这个过程叫做 “序列化” 和 “反序列化”

序列化 和 反序列化

协议就是结构体,服务端和客户端都要认识
在这里插入图片描述
上图就很清晰的展示了序列化与反序列化的过程,我们将结构体信息序列化,转化为特定的字符串格式发送即可,在按照规则反序列化在另一台主机得到结构体。

重新理解 read、write、recv、send 和 tcp 为什么支持全双工

现在我们要在系统层面上复盘一下文件系统。
在这里插入图片描述
我们的进程打开文件后,write函数会将你的数据拷贝内核级文件缓冲区,在由OS刷新到硬盘,这取决于OS的策略。

现在转过头看网络:
在这里插入图片描述

先输出一个结论:其实网络也有缓冲区,在传输层中,而传输层与网络层也都存在OS中。也就是说一个fd有一个连接,一个连接有两个缓冲区。

于是我们根据系统层面的文件理解,现在可以得到一个结论

  1. write read send recv并不是直接从网络中读取写入,本质都是拷贝函数!
  2. 发送数据的本质:是从发送方的发送缓冲区把数据通过协议栈和网络拷贝给接收方的接收缓冲区
  3. 因为有两个缓冲区的存在,读写并不冲突,所以支持全双工
  4. 我们的缓冲区为空或为满时,read或write就会阻塞,就会将PCB放入对应文件的等待队列中。这时就有几个问题了什么时候发?发多少?出错了怎么办? 这些都不用担心,因为我们的TCP(属于传输层,传输层也是在OS)会帮助我们,不然怎么叫传输控制协议?(就像是系统层面,内核缓冲区刷新到外设也是OS干的)
  5. 实际上,缓冲区就是临界资源,上层生产数据放入缓冲区,OS根据策略消费。
  6. 那些拷贝函数为什么会阻塞?
    好像这个结论一致都是别人告诉我们的,真正的原因在于为了维持生产者与消费者的同步!

因为是生产消费者模型,所以缓冲区内可能会积压一部分消息,剩一部分,然后剩的一部分并不能接受到完整的信息,比如hello,缺只收到hel,这也就是字节流。
通俗来说就是客户端发的与服务端收到不一样。
现实中的例子就是自来水厂分配一次的水够你用一个月,自然界你收集10天的水一下就用完了,发送与接收的是可能不一致的。

UDP是属于发快递,有快递包隔开的。

所以我们是不能随便序列化的,需要确保得到正确的信息才能序列化。
那么如何分割完整报文??
请听下回分解~

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 批量查询全国快递单号:高效追踪物流信息
  • HarmonyOS应用开发学习-ArkUI-容器组件
  • springboot的学习(二):常用配置
  • 【算法 04】汉诺塔递归求解和通式求解
  • 【Linux基础】Linux中的开发工具(1)--yum和vim
  • 【学习笔记】Day 11
  • C++11中的左右值引用(略带复习)
  • PyTorch 基础学习(1) - 快速入门
  • 从零开始搭建 LVS 高性能集群 (DR模式)
  • JAVA中的对象流ObjectInputStream
  • uniapp实现自定义弹窗组件,支持富文本传入内容
  • Linux:Linux环境基础开发工具使用
  • DIAdem 与 LabVIEW
  • 【数据结构篇】~顺序表
  • Golang | Leetcode Golang题解之第336题回文对
  • angular学习第一篇-----环境搭建
  • CSS盒模型深入
  • JavaScript DOM 10 - 滚动
  • laravel with 查询列表限制条数
  • laravel 用artisan创建自己的模板
  • Magento 1.x 中文订单打印乱码
  • PHP CLI应用的调试原理
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 从零开始学习部署
  • 对JS继承的一点思考
  • 搞机器学习要哪些技能
  • 关于springcloud Gateway中的限流
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 小李飞刀:SQL题目刷起来!
  • 做一名精致的JavaScripter 01:JavaScript简介
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • ​HTTP与HTTPS:网络通信的安全卫士
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束
  • (web自动化测试+python)1
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (回溯) LeetCode 131. 分割回文串
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)LINQ之路
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • (自用)仿写程序
  • ***详解账号泄露:全球约1亿用户已泄露
  • .net 4.0发布后不能正常显示图片问题
  • .NET 5种线程安全集合
  • .NET C# 使用GDAL读取FileGDB要素类
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Core WebAPI中封装Swagger配置
  • .Net(C#)自定义WinForm控件之小结篇
  • .net6+aspose.words导出word并转pdf
  • .NetCore 如何动态路由
  • .NET程序集编辑器/调试器 dnSpy 使用介绍