“协议” 是一种约定。
计算机之间的传输媒介是光信号和电信号。通过 “频率” 和 “强弱” 来表示 0 和 1 这样的 信息.。要想传递各种不同的信息, 就需要约定好双方的数据格式。
只要通信的两台主机, 约定好协议就可以了么? 定好协议, 但是你用频率表示 01, 我用强弱表示 01, 就好比我用中国话, 你用葡萄牙语一样, 虽然大家可能遵守的一套通信规则, 但是语言不同, 即是订好了基本的协议, 也是无法正常通信的
所以, 完善的协议, 需要更多更细致的规定, 并让参与的人都要遵守。
一般具有定制协议或者标准的资格的组织或者公司都必须是业界公认或者具有江湖地 位的组织或者公司, 下面是文心一言生成的标准制定组织, 大家看一下就可以。
能定制协议标准的组织或公司主要有以下几类:
协议本质也是软件, 在设计上为了更好的进行模块化, 解耦合, 也是被设计成为 层状结构的。
分层可以实现解耦合, 让软件维护的成本更低。
TCP/IP 是一组协议的代名词, 它还包括许多协议, 组成了 TCP/IP 协议簇.
TCP/IP 通讯协议采用了 5 层的层级结构, 每一层都呼叫它的下一层所提供的网络来完成自己的需求.
物理层我们考虑的比较少, 我们只考虑软件相关的内容. 因此很多时候我们直接称为 TCP/IP 四层模型.
首先, 即便是单机, 你的计算机内部, 其实都是存在协议的, 比如: 其他设备和 内存通信, 会有内存协议。 其他设备和磁盘通信, 会有磁盘相关的协议, 比如: SATA, IDE, SCSI 等。 只不过我们感知不到罢了。 而且这些协议都在本地主机各自的硬件中, 通信的成本、 问题比较少。
其次, 网络通信最大的特点就是主机之间变远了。 任何通信特征的变化, 一定会 带来新的问题, 有问题就得解决问题, 所以需要新的协议咯。
TCP/IP 协议本质就是通信主机距离变远了。
TCP/IP 协议的本质是一种解决方案
TCP/IP 协议能分层, 前提是因为问题们本身能分层
操作系统和TCP/IP协议的关系:
传输层最著名的协议就是TCP网络层最著名的协议就是IP而传输层(TCP)和网络层(IP)两层必须实现在内核中,无论OS再怎么不同,这部分大家必须遵守协议,必须一样。
TCP和IP既然是核心,把这个协议整体统称为TCP/IP。
理解TCP/IP协议: OS 源代码一般都是用 C/C++语言写的
主机 B 能识别 data, 并且准确提取 a=10, b=20, c=30 吗? 可以,因为双方都有同样的结构体类型 struct protocol。 也就是说,用同样的代码实现协议, 用同样的自定义数据类型, 天然就具有”共识“, 能够识别对方发来的数据
关于协议的朴素理解: 所谓协议, 就是通信双方都认识的结构化的数据类型 因为协议栈是分层的, 所以, 每层都有双方,都有协议, 同层之间, 互相可以认识对方的协议。
举个例子: 当我们在网购时,收到的东西是你所买的东西以及一个快递单子:
当我们拿到东西的时候一般是把快递单子丢掉,物品留下。快递在转运的过程中,快递单子上面的字段工作人员以及你都是明白上面的意思的。这里的快递单子就相当于结构体数据。
两台主机在同一个局域网中是可以进行通信的,每台主机都需要有一个唯一性标识,称之为MAC地址。
比如你的手机给其他三个手机开了热点,那么这四台手机就在一个局域网中,你的手机相当于一台路由器。
举例: 教室中一群学生在上课,其中有一个叫做张三,老师上课提问:“张三…”,老师喊的是张三,其他同学不会有反应,因为喊的是张三。于是张三站起来了,回答了老师的问题。双方在进行对话中,可以认为是面对面单独对话的,但是周围也有一大堆吃瓜群众,只不过其他同学不做处理。
这里的教室对应局域网,老师对应主机A,张三对应主机B,其他同学分别是主机C、主机D…
这实际上就是局域网通信原理。
08:00:27:03:fb:19
)如下是我的虚拟机的MAC地址:
以太网中, 任何时刻, 只允许一台机器向网络中发送数据,如果有多台同时发送, 会发生数据干扰, 我们称之为数据碰撞,所有发送数据的主机要进行碰撞检测和碰撞避免。没有交换机的情况下, 一个以太网就是一个碰撞域。局域网通信的过程中, 主机对收到的报文确认是否是发给自己的, 是通过目标mac 地址判定。
之前我们在学习系统编程的时候知道访问公共资源就是临界资源,那么这里的局域网就是一个临界资源(以太网中, 任何时刻, 只允许一台机器向网络中发送数据)。
同一个网段内的两台主机进行发送消息的过程:
而其中每层都有协议, 所以当我进行进行上述传输流程的时候, 要进行封装和解包
报头部分, 就是对应协议层的结构体字段, 我们一般叫做报头,除了报头, 剩下的叫做有效载荷,故, 报文 = 报头 + 有效载荷。
网络协议的共性:
数据封装的过程:
数据分用的过程:
IP 地址是在 IP 协议中, 用来标识网络中不同主机的地址,对于 IPv4 来说, IP 地址是一个 4 字节, 32 位的整数。通常也使用 “点分十进制” 的字符串表示 IP 地址, 例如192.168.0.1
; 用点分割的每一个数字表示一个字节, 范围是 0 - 255;
我的虚拟机IP地址:
跨网段的主机的数据传输. 数据从一台计算机到另一台计算机传输过程中要经过一个或 多个路由器
结合封装与解包, 体现路由器解包和重新封装的特点:
用户A将数据从应用层开始向下交付,到了网络层根据目的地址发现不是发给自己局域网主机的报文,就推送给路由器。推送给路由器之前,需要先封装MAC帧。数据通过局域网转发给其他主机,其他主机不考虑。经过网卡,路由器得到数据,进行解包,此时再次向下交付封装报文,原来的MAC地址和目的MAC地址会改变,经过网卡,到达用户B,解包分用,得到数据。
网络层(IP层)向上(包括网络层)看到的所有报文都是一样的,都至少是IP报文。IP可以屏蔽底层网络的差异。
对比 IP 地址和 Mac 地址的区别:
网络通信的宏观流程:
IP 网络层存在的意义: 提供网络虚拟层, 让世界的所有网络都是 IP 网络, 屏蔽 最底层网络的差异
IP在网络中是用来标识主机的唯一性
数据传输到主机不是目的,数据是给用户使用的。比如: 聊天是人在聊天, 下载是人在下载, 浏览网页是人在浏览。 用户是通过启动微信或者QQ进行聊天,通过启动迅雷去下载,通过启动谷歌去浏览。通过启动本质上是通过进程,进程是用户在系统中的代表, 只要把数据给进程, 用户就相当于就拿到了数据
数据传输到主机不是目的, 而是手段。 到达主机内部, 在交给主机内的进程,才是目的
端口号(port)是传输层协议的内容
服务端启动的时候,就一定要和一个port关联起来。
一个进程可以绑定多个端口号,但是一个端口号不能被多个进程绑定。需要通信的进程就需要端口号,凡是需要进行网络通信的进程需要端口号。
进程 ID 属于系统概念, 技术上也具有唯一性, 确实可以用来标识唯一的一个进程, 但是这样做, 会让系统进程管理和网络强耦合, 实际设计的时候, 并没有选择这样做。
端口号划分:
P 地址用来标识互联网中唯一的一台主机, port 用来标识该主机上唯一的一个网络进程
IP+Port 就能表示互联网中唯一的一个进程
通信的时候, 本质是两个互联网进程代表人来进行通信, {srcIp,srcPort, dstIp, dstPort}这样的 4 元组就能标识互联网中唯二的两个进程,网络通信的本质, 也是进程间通信。
把 ip+port 叫做套接字 socke
传输层是属于内核的, 那么我们要通过网络协议栈进行通信, 必定调用的是传输层提供的系统调用, 来进行的网络通信。
内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分。
两个通信的主机之间的存储方式可能不一样,一个大端,一个小端,那么数据就反了。标准规定:凡是在网络通信的,必须大端,TCP/IP 协议规定,网络数据流应采用大端字节序,即低地址高字节.
发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存。网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可。
socket API 是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4、 IPv6,以及 后面要讲的 UNIX Domain Socket. 然而, 各种网络协议的地址格式并不相同.
socket API
可以都用 struct sockaddr *
类型表示, 在使用的时候需要强制转化成sockaddr_in
; 这样的好处是程序的通用性, 可以接收 IPv4, IPv6, 以及 UNIX Domain
Socket 各种类型的 sockaddr 结构体指针做为参数。这实际上就是C++中的多态。
关于Socket套接字编程后续文章会详细讲解。