目录
初识协议
- 协议是一种约定
只要约定好协议就可以实现两台主机通信了吗?
答:不可以,虽然都遵守一个协议,但实现这个协议使用的策略可能不一样,就比如我说中国话,他说德语,虽然遵守同一套规则,但是也无法正常通信。
所以,完善的协议,需要更多标准。
计算机生产厂商很多,计算机操作系统也很多,计算机网络硬件设备也是很多,如何让这些不同厂商生产的计算机能够顺畅通信?所以,有人站出来,约定一个标准,大家都来遵守,这就是网络协议。
协议分层
协议本质也是软件,在设计上为了更好的模块化和解耦合,要被设计成层状结构。分层可以实现解耦合,让软件维护成本变低。
OSI七层模型
OSI组织设计了七层网络模型,是一个逻辑上的定义和规范:
- 把网络从逻辑上分为7层,每一层都有对应的物理设备,如路由器、交换机。
- 从底层到上层依次为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
但是OSI定的七层网络模型非常完善,在实际中,会话层、表示层不可能接入到操作系统中,所以落地的是5层协议。
TCP/IP五层(或四层)模型
TCP/IP是一组协议的代名词,采用5层结构,这5层分别是物理层、数据链路层、网络层、传输层、应用层,其中物理层负责光/电信号的传递方式,但是物理层我们不谈,所以剩下还有4层,这4层是软件的4层。
再识协议
上面我们简单了解了一些概念,下面我们重新理解一下。
为什么要有TCP/IP协议?
即使是单机,也存在协议,比如磁盘协议、内存协议,这些协议都在本地主机各自的硬件上,通信的成本、问题比较少。但是网络通信时距离变远,这带来了很多新问题,需要新的协议来解决。
比如,这四个主机分布于不同省份,主机A想要和主机C通信,一旦主机之间距离变长,就会产生新的问题:
- 我要把数据发给主机C,得先发到路由器R吧?怎么办?
- 网上这么多主机,怎么定位并找到主机C呢?怎么办?
- 如果我的数据发出去,丢失了?怎么办?
- 发数据不是目的,而是手段,用数据才是目的,主机C怎么知道我发出去的数据怎么被处理,被使用呢?
为了解决以上新的问题,就定出了很多协议,这几个问题都是不同性质不同种类的问题,并且上面几个问题要被依次解决才可以。
所以,为什么要有TCP/IP协议呢?本质就是通信主机距离变远了。
什么是TCP/IP协议?
- TCP/IP协议的本质是一种解决方案
- TCP/IP协议能分层,前提是因为问题本身能分层
TCP/IP协议与操作系统的关系
OSI标准定出来以后,Windows工程师和Linux工程师都会自己分别写代码把这个标准实现,虽然Windows和Linux操作系统本身实现是不一样的,但是这双方的网络部分必须要是一样的,这就是不同厂商之间设备可以通信的关键。最重要的两层是传输层和网络层,对应的最著名的协议就是TCP和IP,无论操作系统实现如何不一样,这两层的实现必须一样。TCP和IP既然是核心,把这两个协议整体统称为TCP/IP就不过分了。可以看出,整个协议栈,不仅设计到硬件,还涉及到驱动、OS,甚至用户,所以,这个协议一定需要IT各行各业都要进行支持!
究竟是什么协议
OS源代码一般是C/C++语言写的。
可以理解为虽然两款OS完全不同,但是他们的传输层/网络层都遵循TCP/IP,其网络部分代码实现完全一样。假设在A的传输层定义了一个struct protocol结构体,然后定义一个这样的结构体对象,然后将它发送到B主机,那B能不能识别出来这个对象呢?可以!因为其网络部分代码实现一样,B也有struct protocol结构体类型,直接struct protocol* pdata这个指针指向这块内存。
所以,所谓协议,就是通信双方都认识的结构化的数据类型。因为协议栈是分层的,每层对方都有一样的协议,同层之间可以认识对方的协议。
还可以举一个通俗的例子--快递单(比如买了一个键盘)。快递单上有收件人和寄件人很多信息,这些信息其实可以用结构体来描述,我们最终想要的是键盘。其中,快递单就是协议报头,键盘就是有效载荷。
网络传输基本基本流程
局域网网络传输流程图
局域网(以以太网为例)通信原理
两台主机在同一个局域网,可以直接通信!局域网能直接通信,每台主机(局域网)都要有一个唯一性的标识符:Mac地址。
Mac地址
Mac地址长度为48位,6个字节,一般用16进制数字加上冒号的形式来表示,如上图。实际上,在网卡出厂时,mac地址就已经确定,不能修改,通常是唯一的。
这5个主机在一个局域网中,主机A要给主机E发消息,把消息发送到局域网中,每台主机都能收到这个消息,主机B发现这条消息的dst是MacE,而我是MacB,主机C、D说俺也一样,主机E说这不就是我吗?而主机E也可以以同样的方式给主机A发消息。
这种局域网通信有几个特点:
- 以太网中,任何时刻,只允许一台机器向网络中发送数据。这不相当于局域网是一种临界资源吗!!
- 如果有多台同时发送,会发生数据干扰,称之为"数据碰撞"。
- 所有发送数据的主机要进行碰撞检测和碰撞避免,碰撞避免的方发是随机休眠一定时间,过一会儿再重新发。
除了以太网外,局域网还有令牌环网,即维护一个数据,持有这个数据的主机才能发消息,此时令牌就相当于一把锁。
- 没有交换机的情况下,一个以太网就是一个碰撞域。
- 局域网通信的过程中,主机对收到的报文确认是否是发给自己的,是通过目标mac地址判定
- 正如上面所说,局域网相当于一种临界资源,可以从系统角度来理解局域网通信原理。
小科普:以太网的"以太"是什么意思?
之前的物理学家提出一种假说,在宇宙中,光需要通过"以太"这种介质传播,但是后来被证明光传播不需要介质。随着局域网的诞生,计算机学者需要对局域网命名,把物理学界不存在的"以太"这种物质,在计算机学科中有,于是把这种有碰撞域的局域网命名为"以太网",调侃一下,所以程序员还是挺闷骚的~哈哈哈哈。
初步明白了局域网通信原理,再来看同一个网段内的两台主机进行发送消息的过程:
把数据自顶向下进行交付,最后交给网卡,再由网卡交给另一台主机网卡,自底向上进行交付。而其中每层都有协议,所以进行上述传输流程时,要进行封装和解包:
可以看到,同层之间看到的报文是一样的! 虽然物理上是依次自上而下和自下而上交付,但是逻辑上可以看成是同层在进行通信。
由上而下添加报头的过程可以看作入栈,把整个报文结构想象成栈结构,自下而上解包可以认为是出栈。所以TCP/IP叫做网络协议栈的原因是就是整个报文结构可以看成是一个栈结构!
数据在网络发送时,一定最终要在硬件上跑,所以,主机2一定是硬件先收到数据。
应用层有http、ssh等协议,传输层有tcp、udp协议,网络层有ip、icmp协议,那么问题来了,当数据链路层解包后,应该把数据交给ip协议还是icmp协议呢?网络层要把数据交给tcp还是udp呢?等等。
这里我们先说一下网络协议的共性:
- 报头和有效载荷的分离 -- 解包
- 除了应用层,每一层协议,都必须解决一个问题,自己的有效载荷,要交给上层的哪一种协议 -- 分用
- 报头部分,就是对应协议层的结构体字段,叫做报头
- 除了报头,剩下的叫做有效载荷
- 报文=报头+有效载荷
在这里我们需要明确一下报文的叫法:报文在传输层叫做段,在网络层叫做数据报,在链路层叫做帧。应用层数据通过协议栈发送到网络上时,每层协议都要加上一个数据首部,称为封装。首部信息中包含了一些类似于首部有多长,载荷有多长,上层协议是什么等信息。数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,根据首部中的 "上层协议字段" 将数据交给对应的上层协议处理。
跨网络传输流程图
IP地址
IP地址分为IPv4和IPv6两个版本,默认是IPv4。
IP地址是在IP协议中,标识网络中不同主机的地址;
对于IPv4来说,IP地址是一个 4字节,32位的整数;
通常也使用 "点分十进制" 的字符串表示 IP 地址, 例如 192.168.0.1 ; 用点分割的每一个数字表示一个字节, 范围是 0 - 255;
跨网段的主机的数据传输,数据从一台计算机到另一台计算机传输过程中要经过一个或多个路由器。
在网络中,主机、服务器、路由器都可以叫做主机,而路由器要级联两个网络就要配两张网卡,配上不同的IP,也有不同的IP地址。在上图中,主机a的IP地址是192.168.2.2,路由器在左侧以太网中192.168.2.1,路由器在右侧令牌环网中的IP地址是172.168.2.1,主机b的IP地址是172.168.2.2,说明左右两侧的局域网是不同的网络,主机ab也有各自对应的Mac地址。
刚开始,用户a向下交付数据,经过逐层封装到网络层时,得到的报文如上图左侧,src是192.168.2.2是自己本身,dst是172.168.2.2,这是用户b主机。当数据向下交付到网络层时,除了添加报头外,还有一项非常重要的工作是--路由,虽然主机a不知道要去的dst172.168.2.2是哪,但一定知道不是主机a所在的局域网(明显和主机a所在的192.168.2.不一样),所以,只能把数据交给路由器。那是由网络层直接交给路由器吗?并不是!而是把数据交给数据链路层,并添加报头,新添加的报头里包括:src:MacA、dst:MacLeft,然后将最终的报文转发给局域网,由路由器收到该报文,同时该局域网里的其他主机也收到了该报文,但是根据MacLeft确定出不是发给自己,因此它们不做处理。然后路由器收到该报文后,向上交付给路由器的网络层,并进行解包,解包之后的报文正好是主机A想发的,然后在路由器里进行路由,路由器查看报文里要去的ip地址,发现是172.168.2.2,诶这不和路由器的另一张网卡的ip有点像啊,好像在同一个网段,说明你要去的主机就在我这个局域网啊,此时,路由器再将报文向下交付,加上报头:src:MacRight、dst:MacB,然后主机B的数据链路层就收到了报文,发现目的ip地址就是我自己,然后向上交付。
我们神奇地发现,主机A、路由器、主机B的网络层都收到了同样的报文,所以我们可以得到如下几个结论:
- 网络层(就是IP层)向上(包括网络层)看到的所有报文都是一样的,都至少是IP报文
- IP可以屏蔽底层网络的差异(IP层往下的报文的报头会不一样)
IP地址和Mac地址
这两种地址到底是什么关系呢?我们通过西游记的故事来理解一下:
唐僧从长安城出发去取经,依次路过车迟国、女儿国、火焰山,假设现在到了车迟国,就向车迟国国王说,我从长安来,要去西天取经,上一站是从长安城来的,这一站就到了车迟国,请问下一站应该去哪里呢?车迟国国王一想,他要去西天,那离这里最近的是女儿国,就告诉唐僧下一站去女儿国。在这里,从唐僧表达中车迟国国王得到两套地址:1)从长安来,到西天去2)上一站长安,下一站女儿国。
到了女儿国,告诉女儿国国王我从长安来,到西天去,上一站是从车迟国来的,下一站去女儿国,然后问女儿国国王,我接下来该往哪里走啊?女儿国国王说离我们这里最近的就是火焰山了,你就去火焰山吧。在这里,女儿国国王也得到两套地址:1)从长安来,到西天去2)上一站车迟国,下一站女儿国,然后唐僧得到了新的新的地址:上一站女儿国、下一站火焰山。
到了火焰山,又有人问,唐僧说我从长安来,到西天去,上一站在女儿国,下一站就到了火焰山。
在这个过程中,我们发现在唐僧脑子里,永远存在两套地址,1)从哪来到哪去2)上一站是哪下一站是哪,有一套地址一直不变,这种不变的地址称为IP地址。而每经过一个设备就要变更上一站下一站,这种一直在变的地址称为Mac地址。车迟国、女儿国、火焰山相当于路由器,而车迟国国王、女儿国国王、火焰山领主相当于一张张路由表,方便我们去查,唐僧提供地址信息,国王提供路由信息,两个一结合就知道下一站去哪。
对于这个过程,我们存在这样的问题:
为什么车迟国国王给的建议是去女儿国而不是去其他国家?因为唐僧要去的目的地是西天!
所以,IP地址可以理解为最终目标,而Mac地址是为了达到最终目标所推论出来的下一个目标。
最终网络通信的模式如下:
关于网络通信的理论部分已经有了,接下来我们继续学习socket编程!