本文来自做者 宋璐 在 GitChat 上分享「如何快速入门网络基础知识(TCP/IP 和 HTTP)」,「阅读原文」查看交流实录程序员
「文末高能」算法
编辑 | 嘉仔编程
做用:传输层为它上面的应用层提供通讯服务。缓存
在OSI七层参考模型中,传输层是面向通讯的最高层,也是用户功能的最底层。服务器
传输层两大重要的功能:复用 和 分用。网络
复用:在发送端,多个应用进程公用一个传输层;多线程
分用:在接收端,传输层会根据端口号将数据分派给不一样的应用进程。并发
和网络层的区别:网站
网络层为不一样主机提供通讯服务,而传输层为不一样主机的不一样应用提供通讯服务。spa
网络层只对报文头部进行差错检测,而传输层对整个报文进行差错检测。
UDP只在IP数据报服务的基础上增长了少许的功能:复用与分用、对整个报文的差错检测。
UDP是无链接的
通讯前不须要创建链接,通讯结束也无需释放链接。
UDP是不可靠的
它是尽力而为交付,不能确保每个数据报都送达。
UDP是面向报文的
所谓『面向报文』就是指:UDP数据传输的单位是报文,且不会对数据做任何 拆分 和 拼接 操做。
在发送端,应用程序给传输层的UDP什么样的数据,UDP不会对数据进行切分,只增长一个UDP头并交给网络层。
在接收端,UDP收到网络层的数据报后,去除IP数据报头部后遍交给应用层,不会做任何拼接操做。
UDP没有拥塞控制
UDP始终以恒定的速率发送数据,并不会根据网络拥塞状况对发送速率做调整。这种方式有利有弊。
弊端:网络拥塞时有些报文可能会丢失,所以UDP不可靠。
优势:有些使用场景容许报文丢失,如:直播、语音通话,但对实时性要求很高,此时UDP仍是颇有用武之地的。
UDP支持一对1、一对多、多对多、多对一通讯
而TCP只支持一对一通讯。
UDP首部开销小,只有8字节。
而TCP头部至少由20字节,相比于TCP要高效不少。
PS:问:UDP不可靠具体体如今哪些方面?数据报丢失?数据报顺序?
源端口
目的端口
长度:整个数据报的长度
检验和:整个数据报的检验和。
TCP是面向链接的
通讯前须要创建链接,通讯结束须要释放链接。
TCP提供可靠交付服务
所谓『可靠』指的是:TCP发送的数据无重复、无丢失、无错误、与发送端顺序一致。
TCP是面向字节流的
所谓『面向字节流』指的是:TCP以字节为单位。虽然传输的过程当中数据被划分红一个个数据报,但这只是为了方便传输,接收端最终接受到的数据将与发送端的数据如出一辙。
TCP提供全双工通讯
所谓『全双工通讯』指的是:TCP的两端既能够做为发送端,也能够做为接收端。
一条TCP链接的两端只能有两个端点
TCP只能提供点到点的通讯,而UDP能够任意方式的通讯。
TCP链接 与 套接字
什么是『TCP链接』?
TCP链接是一种抽象的概念,表示一条能够通讯的链路。每条TCP链接有且仅有两个端点,表示通讯的双方。且双发在任意时刻均可以做为发送者和接收者。
什么是『套接字』?
一条TCP链接的两端就是两个套接字。套接字=IP地址: 端口号。所以,TCP链接=(套接字1,套接字2)=(IP1:端口号1,IP2:端口号2)
TCP头部长度有20字节的固定部分,选项部分长度不定,但最多40字节,所以TCP头部在20-60字节之间。
源端口 和 目的端口
传输层和网络层一大重要区别就是传输层指定了数据报发往的应用进程,所以须要端口号标识。
序号
当前TCP数据报数据部分的第一个字节的序号。咱们知道,TCP是面向字节的,它会对发送的每个字节进行编号,并且不一样数据报之间是连续编号的。
因为本字段4字节,能够给[0,2^32-1]个字节进行编号(大约4G),并且序号循环使用,当发送完2^32-1个字节后,序号又从0开始。通常来讲,当2^32-1个字节被发送的时候,前面的字节早就发送成功了,所以序号能够循环使用。
确认号
表示当前主机做为接收端时,指望接收的下一个字节的编号是多少。也表示,当前主机已经正确接收的最后一个字节序号+1。
数据偏移(报文长度)
它代表了数据报头部的长度。
保留字段
标识符
TCP有7种标识符,用于表示TCP报文的性质。它们只能为0或1。
URG=1
当URG字段被置1,表示本数据报的数据部分包含紧急信息,此时紧急指针有效。紧急数据必定位于当前数据包数据部分的最前面,紧急指针标明了紧急数据的尾部。如control+c:这个命令要求操做系统当即中止当前进程。此时,这条命令就会存放在数据包数据部分的开头,并由紧急指针标识命令的位置,并URG字段被置1。
ACK=1
ACK被置1后确认号字段才有效。此外,TCP规定,在链接创建后传送的全部报文段都必须把ACK置1。
PSH=1
当接收方收到PSH=1的报文后,会当即将数据交付给应用程序,而不会等到缓冲区满后再提交。一些交互式应用须要这样的功能,下降命令的响应时间。
RST=1
当该值为1时,表示当前TCP链接出现严重问题,必需要释放重连。
SYN=1
SYN在创建链接时使用。当SYN=1,ACK=0时,表示当前报文段是一个链接请求报文。当SYN=1,ACK=1时,表示当前报文段是一个赞成创建链接的应答报文。
FIN=1
FIN=1表示此报文段是一个释放链接的请求报文。
接收窗口大小
该字段用于实现TCP的流量控制。它表示当前接收方的接收窗口的剩余容量,发送方收到该值后会将发送窗口调整成该值的大小。发送窗口的大小又决定了发送速率,因此接收方经过设置该值就能够控制发送放的发送速率。发送方每收到一个数据报都要调整当前的发送窗口。
检验和
用于接收端检验整个数据包在传输过程当中是否出错。
紧急指针
用于标识紧急数据的尾部。
选项字段
上述字段都是每一个TCP头部必需要有的,而选项字段是可选的,且长度可变,最长40字节。
最经常使用的选项字段为MMS:最大报文长度。
PS:TCP协议中,主动发起请求的一端称为『客户端』,被动链接的一端称为『服务端』。无论是客户端仍是服务端,TCP链接创建完后都能发送和接收数据。
起初,服务器和客户端都为CLOSED状态。在通讯开始前,双方都得建立各自的传输控制块(TCB)。
服务器建立完TCB后遍进入LISTEN状态,此时准备接收客户端发来的链接请求。
第一次握手
客户端向服务端发送链接请求报文段。该报文段的头部中SYN=1,ACK=0,seq=x。请求发送后,客户端便进入SYN-SENT状态。
PS1:SYN=1,ACK=0表示该报文段为链接请求报文。
PS2:x为本次TCP通讯的字节流的初始序号。
TCP规定:SYN=1的报文段不能有数据部分,但要消耗掉一个序号。
第二次握手
服务端收到链接请求报文段后,若是赞成链接,则会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。该应答发送完成后便进入SYN-RCVD状态。
PS1:SYN=1,ACK=1表示该报文段为链接赞成的应答报文。
PS2:seq=y表示服务端做为发送者时,发送字节流的初始序号。
PS3:ack=x+1表示服务端但愿下一个数据报发送序号从x+1开始的字节。
第三次握手
当客户端收到链接赞成的应答后,还要向服务端发送一个确认报文段,表示:服务端发来的链接赞成应答已经成功收到。该报文段的头部为:ACK=1,seq=x+1,ack=y+1。
客户端发完这个报文段后便进入ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时链接的创建完成!
为何链接创建须要三次握手,而不是两次握手?
防止失效的链接请求报文段被服务端接收,从而产生错误。
PS:失效的链接请求:若客户端向服务端发送的链接请求丢失,客户端等待应答超时后就会再次发送链接请求,此时,上一个链接请求就是『失效的』。
若创建链接只需两次握手,客户端并无太大的变化,仍然须要得到服务端的应答后才进入ESTABLISHED状态,而服务端在收到链接请求后就进入ESTABLISHED状态。此时若是网络拥塞,客户端发送的链接请求迟迟到不了服务端,客户端便超时重发请求,若是服务端正确接收并确认应答,双方便开始通讯,通讯结束后释放链接。此时,若是那个失效的链接请求抵达了服务端,因为只有两次握手,服务端收到请求就会进入ESTABLISHED状态,等待发送数据或主动发送数据。但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端链接资源。
TCP链接的释放一共须要四步,所以称为『四次挥手』。咱们知道,TCP链接是双向的,所以在四次挥手中,前两次挥手用于断开一个方向的链接,后两次挥手用于断开另外一方向的链接。
第一次挥手
若A认为数据发送完成,则它须要向B发送链接释放请求。该请求只有报文头,头中携带的主要参数为:FIN=1,seq=u。此时,A将进入FIN-WAIT-1状态。
PS1:FIN=1表示该报文段是一个链接释放请求。
PS2:seq=u,u-1是A向B发送的最后一个字节的序号。
第二次挥手
B收到链接释放请求后,会通知相应的应用程序,告诉它A向B这个方向的链接已经释放。此时B进入CLOSE-WAIT状态,并向A发送链接释放的应答,其报文头包含:ACK=1,seq=v,ack=u+1。
PS1:ACK=1:除TCP链接请求报文段之外,TCP通讯过程当中全部数据报的ACK都为1,表示应答。
PS2:seq=v,v-1是B向A发送的最后一个字节的序号。
PS3:ack=u+1表示但愿收到从第u+1个字节开始的报文段,而且已经成功接收了前u个字节。
A收到该应答,进入FIN-WAIT-2状态,等待B发送链接释放请求。
第二次挥手完成后,A到B方向的链接已经释放,B不会再接收数据,A也不会再发送数据。但B到A方向的链接仍然存在,B能够继续向A发送数据。
第三次挥手
当B向A发完全部数据后,向A发送链接释放请求,请求头:FIN=1,ACK=1,seq=w,ack=u+1。B便进入LAST-ACK状态。
第四次挥手
A收到释放请求后,向B发送确认应答,此时A进入TIME-WAIT状态。该状态会持续2MSL时间,若该时间段内没有B的重发请求的话,就进入CLOSED状态,撤销TCB。当B收到确认应答后,也便进入CLOSED状态,撤销TCB。
为何A要先进入TIME-WAIT状态,等待2MSL时间后才进入CLOSED状态?
为了保证B能收到A的确认应答。若A发完确认应答后直接进入CLOSED状态,那么若是该应答丢失,B等待超时后就会从新发送链接释放请求,但此时A已经关闭了,不会做出任何响应,所以B永远没法正常关闭。
TCP的可靠性表如今:它向应用层提供的数据是 无差错的、有序的、无丢失的,简单的说就是:TCP最终递交给应用层的数据和发送者发送的数据是如出一辙的。TCP采用了流量控制、拥塞控制、连续ARQ等技术来保证它的可靠性。
PS:网络层传输的数据单元为『数据报』,传输层的数据单元为『报文段』,但为了方便起见,能够统称为『分组』。
中止等待协议(ARQ协议)
TCP保证其可靠性采用的是更为复杂的滑动窗口协议,但中止等待协议是它的简化版,为了方便理解,这里先介绍中止等待协议。
AQR协议
ARQ(Automatic Repeat reQuest)自动重传请求。顾名思义,当请求失败时它会自动重传,直到请求被正确接收为止。这种机制保证了每一个分组都能被正确接收。中止等待协议是一种ARQ协议。
中止等待协议的原理
无差错的状况
A向B每发送一个分组,都要中止发送,等待B的确认应答;A只有收到了B的确认应答后才能发送下一个分组。
分组丢失和出现差错的状况
发送者拥有超时计时器。每发送一个分组便会启动超时计时器,等待B的应答。若超时仍未收到应答,则A会重发刚才的分组。
分组出现差错:若B收到分组,但经过检查和字段发现分组在运输途中出现差错,它会直接丢弃该分组,而且不会有任何其余动做。A超时后便会从新发送该分组,直到B正确接收为止。
分组丢失:若分组在途中丢失,B并无收到分组,所以也不会有任何响应。当A超时后也会重传分组,直到正确接收该分组的应答为止。
综上所述:当分组丢失 或 出现差错 的状况下,A都会超时重传分组。
应答丢失 和 应答迟到 的状况
TCP会给每一个字节都打上序号,用于判断该分组是否已经接收。
应答丢失:若B正确收到分组,并已经返回应答,但应答在返回途中丢失了。此时A也收不到应答, 从而超时重传。紧接着B又收到了该分组。接收者根据序号来判断当前收到的分组是否已经接收,若已接收则直接丢弃,并补上一个确认应答。
应答迟到:若因为网络拥塞,A迟迟收不到B发送的应答,所以会超时重传。B收到该分组后,发现已经接收,便丢弃该分组,并向A补上确认应答。A收到应答后便继续发送下一个分组。但通过了很长时间后,那个失效的应答最终抵达了A,此时A可根据序号判断该分组已经接收,此时只需简单丢弃便可。
中止等待协议的注意点
每发送完一个分组,该分组必须被保留,直到收到确认应答为止。
必须给每一个分组进行编号。以便按序接收,并判断该分组是否已被接收。
必须设置超时计时器。每发送一个分组就要启动计时器,超时就要重发分组。
计时器的超时时间要大于应答的平均返回时间,不然会出现不少没必要要的重传,下降传输效率。但超时时间也不能太长。
滑动窗口协议(连续ARQ协议)
连续ARQ协议
在ARQ协议发送者每次只能发送一个分组,在应答到来前必须等待。而连续ARQ协议的发送者拥有一个发送窗口,发送者能够在没有获得应答的状况下连续发送窗口中的分组。这样下降了等待时间,提升了传输效率。
累计确认
在连续ARQ协议中,接收者也有个接收窗口,接收者并不须要每收到一个分组就返回一个应答,能够连续收到分组以后统一返回一个应答。这样能节省流量。TCP头部的ack字段就是用来累计确认,它表示已经确认的字节序号+1,也表示指望发送者发送的下一个分组的起始字节号。
发送窗口
发送窗口的大小由接收窗口的剩余大小决定。接收者会把当前接收窗口的剩余大小写入应答TCP报文段的头部,发送者收到应答后根据该值和当前网络拥塞状况设置发送窗口的大小。发送窗口的大小是不断变化的。发送窗口由三个指针构成:
发送者每收到一个应答,后沿就能够向前移动指定的字节。此时若窗口大小仍然没变,前沿也能够向前移动指定字节。当p2和前沿重合时,发送者必须等待确认应答。
p1
p1指向发送窗口的后沿,它后面的字节表示已经发送且已收到应答。
p2
p2指向还没有发送的第一个字节。p1-p2间的字节表示已经发送,但还没收到确认应答。这部分的字节仍需保留,由于可能还要超时重发。p2-p3间的字节表示能够发送,但尚未发送的字节。
p3
p3指向发送窗口的前沿,它前面的字节还没有发送,且不容许发送。
接收窗口
接收者收到的字节会存入接收窗口,接收者会对已经正确接收的有序字节进行累计确认,发送完确认应答后,接收窗口就能够向前移动指定字节。
若是某些字节并未按序收到,接收者只会确认最后一个有序的字节,从而乱序的字节就会被从新发送。
连续ARQ的注意点
同一时刻发送窗口的大小并不必定和接收窗口同样大。虽然发送窗口的大小是根据接收窗口的大小来设定的,但应答在网络中传输是有时间的,有可能t1时间接收窗口大小为m,但当确认应答抵达发送者时,接收窗口的大小已经发生了变化。此外发送窗口的大小还随网络拥塞状况影响。当网络出现拥塞时,发送窗口将被调小。
TCP标准并未规定未按序到达的字节的处理方式。但TCP通常都会缓存这些字节,等缺乏的字节到达后再交给应用层处理。这比直接丢弃乱序的字节要节约带宽。
TCP标准规定接收方必需要有累计确认功能。接收方能够对多个TCP报文段同时确认,但不能拖太长时间,通常是0.5S之内。此外,TCP容许接收者在有数据要发送的时候捎带上确认应答。但这种状况通常较少,由于通常不多有两个方向都要发送数据的状况。
流量控制
什么是流量控制?
若是发送者发送过快,接收者来不及接收,那么就会有分组丢失。为了不分组丢失,控制发送者的发送速度,使得接收者来得及接收,这就是流量控制。
流量控制的目的?
流量控制根本目的是防止分组丢失,它是构成TCP可靠性的一方面。
如何实现流量控制?
由滑动窗口协议(连续ARQ协议)实现。滑动窗口协议既保证了分组无差错、有序接收,也实现了流量控制。
流量控制引起的死锁
当发送者收到了一个窗口为0的应答,发送者便中止发送,等待接收者的下一个应答。可是若是这个窗口不为0的应答在传输过程丢失,发送者一直等待下去,而接收者觉得发送者已经收到该应答,等待接收新数据,这样双方就相互等待,从而产生死锁。
持续计时器
为了不流量控制引起的死锁,TCP使用了持续计时器。每当发送者收到一个零窗口的应答后就启动该计时器。时间一到便主动发送报文询问接收者的窗口大小。若接收者仍然返回零窗口,则重置该计时器继续等待;若窗口不为0,则表示应答报文丢失了,此时重置发送窗口后开始发送,这样就避免了死锁的产生。
拥塞控制
拥塞控制 和 流量控制 的区别?
PS:拥塞控制是针对于网络而言的,它是防止往网络中写入太多分组,从而致使网络拥塞的状况;而流量控制是针对接收者的,它是经过控制发送者的发送速度保证接收者可以来得及接收。
拥塞控制:拥塞控制是做用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的状况;
流量控制:流量控制是做用于接收者的,它是控制发送者的发送速度从而使接收者来得及接收。
拥塞控制的目的?
缓解网络压力
保证分组按时到达
慢开始算法 和 拥塞避免算法
加法增长:指的是拥塞避免算法,使得发送窗口以线性的方式增加;
乘法减少:指的是无论当前正使用慢开始算法仍是拥塞避免算法,只要发生拥塞时,慢开始门限将会变成当前窗口的一半。
发送方维护一个发送窗口,发送窗口的大小取决于网络的拥塞状况和接收窗口的大小,发送窗口是动态变化的。
发送方还维护一个慢开始门限
算法的具体过程:
慢开始算法的做用:慢开始算法将发送窗口从小扩大,并且按指数级扩大,从而避免一开始就往网络中注入过多的分组从而致使拥塞;它将窗口慢慢扩大的过程其实也在探测网络拥塞状况的过程,当发现出现拥塞时,及时下降发送速度,从而减缓网络拥塞。
拥塞避免算法的做用:拥塞避免算法使发送窗口以线性方式增加,而非指数级增加,从而使网络更加不容易发生拥塞。
AIMD算法(加法增大乘法减少算法)。慢开始算法 和 拥塞避免算法 还有个名称叫作『加法增大乘法减少算法』。
通讯开始时,发送方的发送窗口设为1,并发送第一个分组M1;
接收方收到M1后,返回确认应答,此时发送方发送窗口扩大两倍,并发送M二、M3;(即,发送方每次收到确认应答后,都将发送窗口设为当前值的两倍)
若发送窗口>慢开始门限,则使用拥塞避免算法,每次收到确认应答后都将发送窗口+1;
若发送方出现了超时重传,则代表网络出现拥塞,此时:
a)慢开始门限设为当前发送窗口的一半
b)发送窗口设为1
c)启用拥塞避免算法
PS:发送超时重传时,发送窗口有可能已经超过了慢开始门限,也有可能还没超过;此时无论何种状况,都一概启用拥塞避免算法,并执行上述三步操做!
发送窗口 < 慢开始门限:使用慢开始算法
发送窗口 > 慢开始门限:使用拥塞避免算法
发送窗口 = 慢开始门限:使用慢开始算法或拥塞避免算法
快重传算法 和 快恢复算法
上述慢开始算法和拥塞避免算法能保证网络出现拥塞时进行相应的处理,而快重传和快恢复是一种拥塞预防的方式,此时网络可能还没有出现拥塞,但已经有拥塞的征兆,所以得做出一些预防措施。
快重传原理:由于TCP具备累计确认的能力,所以接收者收到一个分组的时候不会当即发出应答,可能须要等待收到多个分组以后再同一发出累计确认。但快重传算法就要求,接收者若是接收到一个乱序的分组的话,就必须当即发出前一个正确分组的确认应答,这样能让发送者尽早地知道有一个分组可能丢失。
快恢复原理:当发送者收到同一个分组的三个确认应答后,就基本能够判断这个分组已经丢失了;这时候无需等待超时,直接执行『乘法减少加法增大』:
将慢开始门限减半
将发送窗口减半(不设为1)
使用拥塞避免算法
近期热文
福利
「阅读原文」看交流实录,你想知道的都在这里