考虑最简单的状况:两台主机之间的通讯。这个时候只须要一条网线把二者连起来,规定好彼此的硬件接口,如都用USB、电压10v、频率2.4GHz等,这一层就是物理层,这些规定就是物理层协议。android
咱们固然不知足于只有两台电脑链接,所以咱们可使用交换机把多个电脑链接起来,以下图:web
这样链接起来的网络,称为局域网,也能够称为以太网(以太网是局域网的一种)。在这个网络中,咱们须要标识每一个机器,这样才能够指定要和哪一个机器通讯。这个标识就是硬件地址MAC。设计模式
硬件地址随机器的生产就被肯定,永久性惟一。在局域网中,咱们须要和另外的机器通讯时,只须要知道他的硬件地址,交换机就会把咱们的消息发送到对应的机器。缓存
这里咱们能够无论底层的网线接口如何发送,把物理层抽离,在他之上建立一个新的层次,这就是数据链路层。微信
咱们依然不知足于局域网的规模,须要把全部的局域网联系起来,这个时候就须要用到路由器来链接两个局域网:网络
可是若是咱们仍是使用硬件地址来做为通讯对象的惟一标识,那么当网络规模愈来愈大,须要记住全部机器的硬件地址是不现实的;并发
同时,一个网络对象可能会频繁更换设备,这个时候硬件地址表维护起来更加复杂。这里使用了一个新的地址来标记一个网络对象:IP地址。socket
经过一个简单的寄信例子来理解IP地址。spa
我住在北京市,我朋友A住在上海市,我要给朋友A写信:计算机网络
所以,这里IP地址就是一个网络接入地址(朋友A的住址),我只须要知道目标IP地址,路由器就能够把消息给我带到。在局域网中,就能够动态维护一个MAC地址与IP地址的映射关系,根据目的IP地址就能够寻找到机器的MAC地址进行发送。
这样咱们不需管理底层如何去选择机器,咱们只须要知道IP地址,就能够和咱们的目标进行通讯。这一层就是网络层。网络层的核心做用就是提供主机之间的逻辑通讯。
这样,在网络中的全部主机,在逻辑上都链接起来了,上层只须要提供目标IP地址和数据,网络层就能够把消息发送到对应的主机。
一个主机有多个进程,进程之间进行不一样的网络通讯,如边和朋友开黑边和女友聊微信。个人手机同时和两个不一样机器进行通讯。
那么当个人手机收到数据时,如何区分是微信的数据,仍是王者的数据?那么就必须在网络层之上再添加一层:运输层:
运输层经过socket(套接字),将网络信息进行进一步的拆分,不一样的应用进程能够独立进行网络请求,互不干扰。
这就是运输层的最本质特色:提供进程之间的逻辑通讯。这里的进程能够是主机之间,也能够是同个主机,因此在android中,socket通讯也是进程通讯的一种方式。
如今不一样的机器上的应用进程之间能够独立通讯了,那么咱们就能够在计算机网络上开发出形形式式的应用:如web网页的http,文件传输ftp等等。这一层称为应用层。
应用层还能够进一步拆分出表示层、会话层,但他们的本质特色都没有改变:完成具体的业务需求 。和下面的四层相比,他们并非必须的,能够归属到应用层中。
最后对计网分层进行小结:
这里须要注意的是,分层并非在物理上的分层,而是逻辑上的分层。经过对底层逻辑的封装,使得上层的开发能够直接依赖底层的功能而无需理会具体的实现,简便了开发。
这种分层的思路,也就是责任链设计模式,经过层层封装,把不一样的职责独立起来,更加方便开发、维护等等。
TCP并非把应用层传输过来的数据直接加上首部而后发送给目标,而是把数据当作一个字节 流,给他们标上序号以后分部分发送。这就是TCP的面向字节流特性:
面向字节流的好处是无需一次存储过大的数据占用太多内存,坏处是没法知道这些字节表明的意义,例如应用层发送一个音频文件和一个文本文件,对于TCP来讲就是一串字节流,没有意义可言,这会致使粘包以及拆包问题,后面讲。
前面讲到,TCP是可靠传输协议,也就是,一个数据交给他,他确定能够完整无误地发送到目标地址,除非网络炸了。他实现的网络模型以下:
对于应用层来讲,他就是一个可靠传输的底层支持服务;而运输层底层采用了网络层的不可靠传输。虽然在网络层甚至数据链路层就可使用协议来保证数据传输的可靠性,但这样网络的设计会更加复杂、效率会随之下降。把数据传输的可靠性保证放在运输层,会更加合适。
可靠传输原理的重点总结一下有:滑动窗口、超时重传、累积确认、选择确认、连续ARQ。
要实现可靠传输,最简便的方法就是:我发送一个数据包给你,而后你跟我回复收到,我继续发送下一个数据包。传输模型以下:
这种“一来一去”的方法来保证传输可靠就是中止等待协议(stop-and-wait)。不知道还记不记得前面TCP首部有一个ack字段,当他设置为1的时候,表示这个报文是一个确认收到报文。
而后再来考虑另外一种状况:丢包。网络环境不可靠,致使每一次发送的数据包可能会丢失,若是机器A发送了数据包丢失了,那么机器B永远接收不到数据,机器A永远在等待。
解决这个问题的方法是:超时重传。当机器A发出一个数据包时便开始计时,时间到还没收到确认回复,就能够认为是发生了丢包,便再次发送,也就是重传。
但重传会致使另外一种问题:若是原先的数据包并无丢失,只是在网络中待的时间比较久,这个时候机器B会受到两个数据包,那么机器B是如何辨别这两个数据包是属于同一份数据仍是不一样的数据?
这就须要前面讲过的方法:给数据字节进行编号。这样接收方就能够根据数据的字节编号,得出这些数据是接下来的数据,仍是重传的数据。
在TCP首部有两个字段:序号和确认号,他们表示发送方数据第一个字节的编号,和接收方期待的下一份数据的第一个字节的编号。
中止等待协议已经能够知足可靠传输了,但有一个致命缺点:效率过低。发送方发送一个数据包以后便进入等待,这个期间并无干任何事,浪费了资源。解决的方法是:连续发送数据包。模型以下:
和中止等待最大的不一样就是,他会源源不断地发送,接收方源源不断收到数据以后,逐一进行确认回复。这样便极大地提升了效率。但一样,带来了一些额外的问题:
发送是否能够无限发送直到把缓冲区全部数据发送完?不能够。由于须要考虑接收方缓冲区以及读取数据的能力。若是发送太快致使接收方没法接受,那么只是会频繁进行重传,浪费了网络资源。因此发送方发送数据的范围,须要考虑到接收方缓冲区的状况。这就是TCP的流量控制。
解决方法是:滑动窗口。基本模型以下:
在TCP的首部有一个窗口大小字段,他表示接收方的剩余缓冲区大小,让发送方能够调整本身的发送窗口大小。经过滑动窗口,就能够实现TCP的流量控制,不至于发送太快,致使太多的数据丢失。
连续ARQ带来的第二个问题是:网络中充斥着和发送数据包同样数据量的确认回复报文,由于每个发送数据包,必须得有一个确认回复。提升网络效率的方法是:累积确认。
接收方不须要逐个进行回复,而是累积到必定量的数据包以后,告诉发送方,在此数据包以前的数据全都收到。例如,收到 1234,接收方只须要告诉发送方我收到4了,那么发送方就知道1234都收到了。
第三个问题是:如何处理丢包状况。在中止等待协议中很简单,直接一个超时重传就解决了。但,连续ARQ中不太同样。
例如:接收方收到了 123 567,六个字节,编号为4的字节丢失了。按照累积确认的思路,只能发送3的确认回复,567都必须丢掉,由于发送方会进行重传。这就是GBN(go-back-n) 思路。
可是咱们会发现,只须要重传4便可,这样不是很浪费资源,因此就有了:选择确认SACK 。在TCP报文的选项字段,能够设置已经收到的报文段,每个报文段须要两个边界来进行肯定。这样发送方,就能够根据这个选项字段只重传丢失的数据了。
到这里关于TCP的可靠传输原理就已经介绍得差很少。最后进行一个小结:
固然,这只是可靠传输的冰山一角,感兴趣能够再深刻去研究。
来源:https://www.toutiao.com/i6954...