任何系统之间,如果需要通信,都需要一套自己的协议系统。这个协议系统一般要定义互相通信的语言,以及硬件。
OSI是被提取抽象出来的系统间通信模型,中文意思是“开放式系统互联”,是描述多个系统之间交流的通用模型。
OSI模型
OSI初步
在讲OSI之间,我们首先看一个例子,PC a向PC b发送数据包的过程如下:
- a在内存中通过定义的语言生成数据包
- 将数据包通过总线传给TCP/IP协议处理单元,告诉对方的IP地址、UDP还是TCP、端口号
- TCP/IP处理模块收到包之后,封装,通过总线发送给以太网卡
- 以太网卡再进行编码,变成高低电平震荡发给交换机
- 交换机将数据包交换到b的接口
- b输送到以太网卡的解码芯片,去掉以太网头然后产生中断,将数据包送到内存
- TCP/IP处理模块提取IP头和TCP头,以便区分应该输送到哪个应用程序的缓冲区内存。
- 送到b的应用程序缓冲区内存
可以发现里面最重要的就是三个元素
- 连:通信双方需要连通起来。
- 找:指的是通信双方必须能区分自己和对方。
- 发:定义了如何将数据发到对方。
OSI的七个层次
OSI模型将系统通信划分为了7个层次,最上面的三个层次可以归属到应用层。这个层不需要关心如何将数据传送到对方,只关心如何组织和表达数据。
应用层
应用层是OSI的最上层,表示一个系统对另一个系统要传达的最终消息。
只关注数据, 不关注指令如何发送
表示层
表示层就是对应用层数据的一种表示。
发送方必须用双方规定好的格式来表示信息:可以嵌入在实体数据中。
会话层
会话层:建立会话交互机制。实际是双方的应用程序之间的交互。
应用层、表示层、会话层的数据内容都被封装起来,交给押运员传输层
。
TCP/IP只有4层:应用层、传输层、网络层、物理链路层,它将OSI的应用层、表示层、会话层合并为一层,即应用访问层
。意思是这个层全部与应用程序相关的逻辑,与网络通信无关。应用程序只需要调用下层的接口就可以完成通信。
下四层的作用是把上三层的数据成功送到目的地。
传输层
典型的传输层程序如下:
- TCP协议的作用是保证上层数据能传输到目的地。类似货运公司的押运员,不管通过什么渠道(直达还是下一跳),不管物理链路的类型,只要送到即可。
- 如果出现错误,需要重新发送。每件货物到了目的地必须找收件人签字(TCP的ACK应答包)或者一批货物到了以后一次性签收。(滑动窗口)
- 最后回公司登记
TCP主要处理拥塞和流量控制。路由器是调度中心,它可以决定走哪条路。TCP不能调度,它只是在发生了拥挤就只能通知后续的货物慢点发。如果道路畅通,则通知后面的货物加速发送。
那么TCP是怎么知道链路是否拥塞呢?它可以通过接收方返回的ACK应答来判断链路拥挤的。如果半天都没收到对方的签字,说明拥塞,有丢失
** 传输层的程序一定运行在通信双方的终端设备上。**而不是在中间的互联设备上。
因为传输层是一种端到端的保障机制,必须保证成功收到了并成功处理数据,才算发送成功了。如果只到了对方的网卡,但是断电了,也不叫端到端保障。
具体的可以再看从输入网址到浏览器返回内容(二),TCP/IP篇
网络层
上面说到了传输层其实只是一个押运员,它并不能进行调度,那么如何选路就交给了网络层。
同样以客户寄货物为例,当客户把货物交给货运公司的时候,会填写目的地址,至于应该走哪条路,统统不管,全部交给网络层处理。
- 货运公司为每件货物贴上IP头地址标签
- 货运公司掌握了全球范围的地址信息(路由表)
- 选择了一条路就上路。
- 货物每中转到一个地方就交给那个地方的调度,由调度来决定下一站到哪里。
- 旧调度不必告诉新调度最终的目的怎么走,因为所有调度都知道最终的目的。
总结一下就是,客户寄送货物的时候需要给出最终的目的地址,不管这个货物途径哪个中转站,所有的中转站都会知道最终的目的地址。
比如,要从新疆将货物寄到青岛,但是新疆到青岛没有直到的火车,所以只能去北京转出。
那么新疆的调度会去查找路由表,发现必须先到北京。注意此时在货物上贴上的还是青岛的标签,而不是北京的标签,但是会将货物发到去北京的火车上。
货物到北京,查看最终的目的地,会查找北京调度中心的路由表,此路由表与新疆的表不同。于是将货物送到去青岛的火车。
可以看出** 路由器就是调度的角色**
比如从青岛访问北京的服务器,具体步骤如下:
- 首先必须知道服务器的IP地址,用这个IP地址作为最终目的地址组装成数据包,发送给青岛的Internet提供商(下面叫运营商)的路由器
- 运营商的路由器解析目的IP地址,发现应该从1号端口发送出,于是发到了河北的另一台路由器。
- 河北路由器根据目的IP查找路由表,发现需要从8口出
- 多次中转以后,发到了北京的路由器。
- 最终到了北京的服务器,将这个包传送到这台服务器的网卡,并提交到TCP/IP协议处理的内存空间。
- 发现是一个TCP握手数据包,所以返回一个确认包,三次握手完成后,就可以向服务器发送HTTP请求来获取网页资源。
在中转的过程中,目的IP并不会改变,改变的只是MAC地址,也就是说会将MAC地址改为下一站的地址。
数据链路层
数据链路层:连通两个设备之间的链路,将上层的数据包再次打包成对应链路特定的格式。按照对应链路的规则在链路上传输给对方。
数据链路就好比交通规则:上路之前还需要看公路的质量怎么样,和对方商量传输的事宜。
链路层的作用:
- 协商链路参数:双工、速率、链路质量
- 打包成帧,加上同步头,一次传输一句或者一个字符一个字符(取决于上层的选择)
- 链路层程序调用物理层提供的接口,将帧交给物理层。
- 提供一些保障机制,在每个帧之后加一个校验字段。如果不符说明链路干扰,直接丢弃,不过不会报告错误,因为上层对链路层的错误不关心。接收方的传输层会感知某个包没有到达,重新传送不完整的包。链路层只侦错,不纠错。
两台PC之间的通信和两个路由器之间通信是有区别的。
路由间的通信:
简单的路由设备工作在OSI的第三层,即网络层,没有上4层的处理逻辑。
所以收到包之后,只检查包中的IP地址,不改变IP头之上的其他内容。
如果有NAT功能的路由器,会对IP包的源或者目的IP地址做修改。
下图为通信路径上各个设备所作用的层次示意图:
- PC A上的浏览器要访问PC B上的Web服务,首先调用WinSock接口,访问OS内核中的TCP/IP协议栈,将目的IP和目的端口以及数据(HTTP GET请求)告诉TCP/IP协议栈
- 协议栈发现与
PC B
不存在链接,所以通过三次握手与B的协议栈建立连接。(A的协议栈组装第一次握手包,发给OS的内核缓冲区,调用网卡驱动从缓冲区将IP包编码并传递出去,因为握手包很小,所以只需要一个帧。) - 帧到达路由器A的缓冲区,产生中断信号,去掉以太网头,发送到
路由器A
的内存,等待IP转发逻辑块处理(IP路由协议计算模块),分析出IP包的头部目的IP地址,查找路由表确定出去的端口号,所以IP路由运算一定要高效。 - 查找出后,从
网卡2
出发送到路由器B的网卡2
.通过同样的过程,发送到PC B
的网卡缓冲区,网卡产生中断,通过总线传送到TCP/IP的协议栈缓冲区内存。 PC B
的协议栈分析出IP是自己的,端口号是80,同时握手标识位是二进制1,就知道是从源设备向Web服务程序所监听的端口发起的握手连接。所以回复IP包给PC A
,PC A再回一个最终确认的包。- 握手成功,
PC A
的协议栈将缓冲区中有浏览器发送过来的HTTP GET请求数据组装成TCP/IP数据包发送给PC B
。PC B获得数据包之后,分析TCP 端口号,根据对应关系将数据放到监听这个端口的应用程序的缓冲区内存。 - 应用程序收到GET请求后,触发Web服务逻辑流程,返回Web数据。同样由B的协议栈发送给
PC机 A
。
未收到确认的包会放到缓冲区中,不会删除,直到收到对方的确认。
所以即使中途的设备把包丢弃了,运行在两端的TCP/IP协议依然会重传,这就是端到端的保障,因为设备中途网络设备不会缓存发送的数据,更不会自动重传。
现在我们来对比一下IP头和TCP头的区别:
- IP头是个标签,用来查看是谁发的货物。
- TCP头是用来确认由哪个上层应用程序来处理收到的包。(用端口号来决定)
物理层
物理层
:在一种介质上将数据编码发送给对方。
注意链路层是控制物理层的。
我们可以把物理层看做传送带,不会进行货物分批,所以需要链路层给每批货物加标志性的头,接收方看到标志了以后就知道新一批货物来了。
经过物理层编码后,最终变成了一串bit流。通过电路振荡传输给对方,收到bit流之后,提交给链路层程序,剥去链路层同步头、帧头帧尾、控制字符。
MTU ,最大传输单元:每种链路都有自己最合适的分批大小
如果一次传输传送大于这个大小的货物,超过了链路接收放的处理吞吐量,会造成缓冲区溢出。
不过TCP和IP协议都会给货物分批。TCP会首先给货物分批,到了IP层,会按照链路层的分批大小来进行分批,如果TCP的分批大小已经小于链路层的分批,不会再分。
被IP层分批的货物,最终会由接受方的IP层再组装,但是由TCP分批的货物,接收方的TCP层不会合并。对货物的处理分析全部交由上层的应用程序来处理