20210215!重要!我需要了解tcp udp底层,从而对tcp的面向数据流有更深的了解 - ziyouzy/2021blog GitHub Wiki

https://www.cnblogs.com/yinzhengjie2020/p/12717312.html

20210215年10点37分:
此时此刻我在研究net.Conn;net.Conn.Read();以及zadapter的新数据生成所连带的创建缓存问题:

不用太在意net.Conn所扮演的角色
需要在意的是他的Read()方法:
    conn.Read(buf)
他的职责其实就是构建缓存单元的一部分
之前探讨过,每个adapter必然会“创建新的东西”
有时只是个signal,而大部分情况下都会事signal+cache
而一旦需要无中生有一个“cache”,则必然在for{}结构内部存在:
    cache := creatCacheFunction
conn.Read()是:=右边的一种可能性
其实conn.Read()有古老辉煌的历史,他是TcpSocket技术的一部分(golang进行了对tcp的封装)
他的内部会解析一个完整的Tcp数据报文,并将报头、尾剪去
呈现给接收端初始的数据

上面仅仅是在探讨Read函数,接下来咱们先来探讨基于类似Read()从而实现某种结构缓存的方法:
golang自身的设计决定了这个缓存的结构类型是[]byte,传入某个字节切片的地址后进行scanf的性质的被动操作,从而给cache(也就是这个buf)填充好数据

其中这步“创建新数据(cache)”整体上会存在三种(四种)分型:

  • 1.面向tcp/udp等net.Conn创建新数据 这种情况下每次Read操作,拿到的[]byte的数据长度是与发送端约定好的长度

  • 2.面向serial(串口)创建新数据 这种情况下每次Read操作,拿到的[]byte的数据长度是不可控的,由于较为底层,无法和发送端约定长度,但是可以和发送端约定协议规则
    或者说
    1之所以可以约定长度,是因为先人已经帮你实现了协议规则,也就是tcp或udp
    而对于2这种情况你需要先自己实现某个较为简化的协议规则实现“客户端与服务端之间的文件级数据包同步”
    再或者说
    串口通信需要先面向不可控数据包实现通信协议实现“客户端与服务端之间的文件级数据包同步”,再面向文件级同步数据实现通信
    而1可以理解成直接面向文件级同步数据实现通信,因为“文件级同步数据实现通信”已经通过tcpSocket完成了
    再说的大一些,通信协议的本质都是在于封装网口实现“文件级同步数据”
    1和2的区别起始就是在于少了这一层的设计,程序员需要自己来实现

  • (3).面向用户输入创建新数据(fmt.Scanln(“哈哈哈”))
    这里起始只是让你更形象的明白1和2到底是什么,本质其实和3一样
    本质是外界(用户,其他终端)与本地终端的数据传递
    人会通过键盘或手柄再通过serial,蓝牙等对“这台机器”进行数据传入,其他的某种机器则是直接通过serial或网口(或蓝牙等)进行数据传入

  • 4.面向多个管道型数据创建新数据,也就是对管道型数据进行聚合,他和1-3是完全不同的两个概念

可是对于“实现聚合”的这个过程,其实在逻辑地位上和“实现文件级同步数据”是一样的
可以想象到的是两者都会存在自身的逻辑(函数)以及各自拥有各种内部字段(临时变量)进行逻辑操作:

  • 如serial需要先确认包头字节从而确定报文长度,报头字节会是个临时变量,报头不同则接下来所创建的字节数组的长度也会不同,等等这些工序都需要创建临时变量得以支持逻辑实现
  • 而对于数据聚合也是一样,如何才能将不同管道数量,不同数据类型的数据聚合成一个数据,这些同样需要创建临时变量得以支持逻辑实现

以后定会有一篇名为《实现聚合与实现文件级同步数据协议栈》的文章来探讨这个问题