精华内容
下载资源
问答
  • 传输层协议

    千次阅读 2018-10-20 21:53:56
    1 传输层协议 网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。传输层提供了进程间的逻辑通信,传输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个传输层实体之间...

    传输层

    1 传输层协议

    网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。传输层提供了进程间的逻辑通信,传输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个传输层实体之间有一条端到端的逻辑通信信道。

    传输层主要协议:UDP、TCP

    UDP 和 TCP 的特点

    用户数据报协议 UDP(User Datagram Protocol)是无连接的,尽最大可能交付,没有拥塞控制,面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信。
    
    传输控制协议 TCP(Transmission Control Protocol)是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)。
    

    2 UDP 首部格式

    首部字段只有 8 个字节,包括源端口、目的端口、长度、检验和。12 字节的伪首部是为了计算检验和临时添加的。

    3 TCP 首部格式

    TCP报文段首部的前20个字节是固定的,后面有4N字节是根据需要而增加的选项。因此TCP报文段的最小长度为20个字节。

    首部固定部分的各字段的意义如下:

    1. 源端口和目的端口:加上IP首部的源IP地址和目的IP地址,确定唯一的一个TCP连接。另外通过目的端口来决定TCP将数据报交付于那个应用程序,从而实现TCP的分用功能。

    2. 序号:占4个字节,序号的范围为[0,4284967296]。由于TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号,首部中的序号字段则是指本报文段所发送的数据的第一个字节的序号。另外,序号是循环使用的,当序号增加到最大值时,下一个序号就又回到了0。

    3. 确认号:当ACK标志位为1时有效,表示期望收到的下一个报文段的第一个数据字节的序号。确认号为N,则表明到序号N-1为止的所有数据字节都已经被正确地接收到了。

    4. 头部长度:TCP报文段的头部长度,它指出TCP报文段的数据部分的起始位置与TCP报文段的起始位置的距离。头部长度占4个字节,但它的单位是32位字,即以4字节为计算单位,因此头部长度的最大值为15*4=60个字节,这就意味着选项的长度不超过40个字节。

    5. 保留位:必须为0.

    6. 下面的六个控制位说明报文段的性质

    1)URG:与首部中的紧急指针字段配合使用。URG为1时,表明紧急指针字段有效,发送应用进程告诉发送方的TCP有紧急数据要传送,于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而其后面仍是普通数据。

    2)ACK:仅当ACK=1时确认号字段才有效,当ACK=0时,确认号无效。TCP规定,在连接建立后所有的传送报文段都必须把ACK置1。

    3)PSH:如果发送的报文段中PSH为1,则接收方接受到该报文段后,直接将其交付给应用进程,而不再等待整个缓存都填满后再向上交付。

    4)RST:复位标志,RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后重新建立运输连接。

    5)SYN:同步序号,用来发起一个连接。当SYN=1而ACK=0时,表明这是一个连接请求报文段,若对方同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。

    6)FIN:用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已发送完毕,并要求释放连接。

    1. 窗口:接收方让发送方下次发送报文段时设置的发送窗口的大小。

    2. 校验和:校验的字段范围包括首部和数据这两部分。

    3. 紧急指针:紧急指针当URG=1时才有效,它指出本报文段中的紧急数据的字节数。值得注意的是,即使窗口为0时,也可发送紧急数据。

    4. 选项与填充:选项应该为4字节的整数倍,否则用0填充。最常见的可选字段是最长报文大小MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段中指明这个选项。它指明本端所能接收的最大长度的报文段。该选项如果不设置,默认为536(20+20+536=576字节的IP数据报),其中ip首部和tcp首部各20个字节,而internet 上标准的MTU (最小)为576B。

    3. TCP 的三次握手

    假设 A 为客户端,B 为服务器端。

    首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。

    A 向 B 发送连接请求报文,SYN=1,ACK=0,选择一个初始的序号 x。

    B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为 x+1,同时也选择一个初始的序号 y。

    A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为 y+1,序号为 x+1。

    B 收到 A 的确认后,连接建立。

    三次握手的原因

    第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。

    客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。

    4. TCP 的四次挥手

    以下描述不讨论序号和确认号,因为序号和确认号的规则比较简单。并且不讨论 ACK,因为 ACK 在连接建立之后都为 1。

    A 发送连接释放报文,FIN=1。

    B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据。

    当 B 不再需要连接时,发送连接释放报文,FIN=1。

    A 收到后发出确认,进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)后释放连接。

    B 收到 A 的确认后释放连接。


    四次挥手的原因

    客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。

    TIME_WAIT

    客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:

    确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。

    等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。

    5 客户端、服务端状态变更

    客户端状态变更


    服务端状态变更

    6. TCP 的性质

    6.1 TCP 可靠传输

    TCP 使用超时重传来实现可靠传输:如果一个已经发送的报文段在超时时间内没有收到确认,那么就重传这个报文段。

    一个报文段从发送再到接收到确认所经过的时间称为往返时间 RTT,加权平均往返时间 RTTs 计算如下:

    其中 RTTd 为偏差。

    6.2 交互数据流和成块数据流

    交互数据类型,如:Telnet,这类协议一般只做小流量的数据交换,比如每按下一个键,要回显一些字符。

    成块数据类型,如:FTP,这类协议需要传输的数据比较多,一般传输的数据量比较大。

    6.2.1 交互数据流

    针对交互性要求比较高的应用,每发送一个字节到服务端,并回显到客户端的过程如下:

    1. 客户端产生一个41bit长的报文(20字节的IP首部,20字节的TCP首部,1字节的数据),发送到服务端;

    2. 服务端发送过来一个40bit的确认报文;

    3. 服务端发送回显的字符,报文长为41bit;

    4. 客户端发送确认报文,报文长为40bit。

    如果在局域网中,通常不会有什么麻烦,因为局域网一般不会出现拥塞,但在广域网中,这些小分组则会增加网络拥塞出现的可能。为了提高这类数据的发送效率和降低网络负担,TCP采用了两种策略:捎带ACKNagle算法

    捎带 ACK :
       捎带ACK的意思是,当接收端接收到TCP报文段后,并不立即发送ACK报文,而是等上一段时间,如果这段时间里该主机有数据要发送到远程主机,就将该数据捎带上ACK一起发送过去,很明显,这样可以减少传输开销。为了防止产生超时重传,绝大多数情况下,这个等待时间为200ms,超过了200ms,如果没有数据要一起发送,就直接发送ACK报文。

    捎带ACK的策略一般也只有在交互性比较高的应用中才会使用,对于成块数据流,一般大多数应用程序不会同时在两个方向上发送数据。

    Nagle算法
      该算法的重点是要求在TCP连接上组多只能有一个未被确认的数据报在传输。算法的大致思路如下:应用程序把要发送的数据逐个字节地从到TCP的发送缓存,发送方把前面的一部分数据先发送出去,并把后面到达的字节继续缓存起来,当发送方收到前面字节的确认后,再把发送缓冲中的所有数据组装成一个报文段发送出去,同时继续对随后到来的数据进行缓存。只有收到前一个报文段的确认后才能继续发送下一个报文段。另外,Nagle算法还规定,当发送缓存中的数据已达到发送窗口大小的一半或已达到报文段的MSS值时,就立即发送一个报文段。
      当数据到达较快而网络速率较慢时,用这种方法可明显地减少所用的网络带宽。很明显,该算法也是专门为交互性高的应用而设计的,对于成块数据流,如果每收到一次确认才能发送下一个报文段,那么传输速率就会很低。

    6.2.2 成块数据流

    对于一些数据吞吐量要求较高的应用,总是希望每次发送尽可能多的数据到主机,对于这类应用,TCP使用滑动窗口协议,该协议允许发送方在停止发送前和等待确认前可以连续发送多个分组,因此可以加速数据的传输。

    滑动窗口

    滑动窗口的滑动是以字节为单位的,发送方A和接收方B在TCP三次握手的前两次握手时协商好了发送窗口和接受窗口的大小,发送方A根据B发送来的确认连接报文中标明的窗口的大小,来确定收到确认前的最大发送数据量,如果A接收到的B发来的确认报文中标明的窗口大小为0,则停止发送数据,直到收到不为0的确认报文,再继续发送。发送窗口表示在没有收到B的确认的情况下,A可以连续把窗口内的数据都发送出去,凡是已发送过的数据,在没有收到确认前都要暂时保留,以便超时重传时使用。

    需要注意的一点是:使用TCP滑动窗口协议时,接收方不必确认每一个收到的分组,在TCP中,ACK确认是累积的,可以在接收到几个序号连续的报文段后只发送一个ACK确认报文,但累积等待的时间最长不能超过0.5秒,以防止发送端超时重传。

    另外,要注意滑动窗口的三种变化:

    1. 窗口合拢。窗口左边沿向右边沿靠近,这种情况发生在数据被发送后收到确认时;

    2. 窗口张开。窗口右边沿向右移动,说明允许发送更多的数据,这种情况发生在另一端的接收进程从TCP接收缓存中读取了已经确认的数据时;

    3. 窗口收缩。窗口右边沿向左移动,一般很少发生,RFC也强烈不建议这么做,因为很可能会产生一些错误,比如一些数据已经发送出去了,又要收缩窗口,不让发送这些数据。

    另外,窗口的左边沿是肯定不可能左移的,如果接收到一个指示窗口左边沿向左移动的ACK,则它被认为是一个重复ACK,并被丢弃。

    总结以下几点:

    1. 发送方不必发送一个全窗口大小的数据,一次发送一部分即可。

    2. 窗口的大小可以减小,但是窗口的右边沿却不能向左移动。

    3. 接收方在发送一个ACK前不必等待窗口被填满。

    4. 窗口的大小是相对于确认序号的,收到确认后的窗口的左边沿从确认序号开始。

    发送接收缓冲区

    1. 缓冲空间和序号空间都是有限的,并且都是循环使用的。

    2. 窗口大小一定不大于收发缓冲区的大小

    3. 发送缓冲区用来暂存发送方准备发送的TCP报文段和已发送但尚未收到确认的数据。

    4. 接收缓冲区用来暂按序到达但尚未被上层应用程序读取的数据合未按序到达的数据。

    6.3 四大定时器

    对于每个TCP连接,TCP一般要管理4个不同的定时器:重传定时器坚持定时器保活定时器2MSL定时器

    6.3.1 重传定时器

    很明显重传定时器是用来计算TCP报文段的超时重传时间的(至于超时重传时间的确定,这里涉及到一大堆的算法,书上有说,我这里不细谈了)。每发送一个报文段就会启动重传定时器,如果在定时器时间到后还没收到对该报文段的确认,就重传该报文段,并将重传定时器复位,重新计算;如果在规定时间内收到了对该报文段的确认,则撤销该报文段的重传定时器。

    6.3.2 坚持定时器

    上篇文章中已经提到了,主要是为了应付零窗口大小通知可能导致的死锁问题。如果接收端在向发送端发送了零窗口报文段后不久,接收端的接收缓存又有了一些存储空间,于是接收端向发送端发送了一个非零窗口大小的报文段,然而这个报文段在传送过程中丢失了,发送端没有收到该报文段,就一直等待接收端发送非零窗口的报文通知,而接收端并不知道报文段丢失了,而是觉得已经告诉发送端了,就会一直等待发送端发送数据,如果没有任何措施的话,这话死锁的局面会一直延续下去。

    为了解决这个问题,TCP为每一个连接设有一个坚持定时器(也叫持续计数器)。只要TCP连接的一方收到对方的零窗口通知,就启动坚持定时器。若坚持定时器设置的时间到期,就发送一个零窗口控测报文段(该报文段只有一个字节的数据,它有一个序号,但该序号永远不需要确认,因此该序号可以持续重传),之后会出现以下三种情况:

    1. 对方在收到探测报文段后,在对该报文段的确认中给出现在的窗口值,如果窗口值仍未零,则收到这个报文段的一方将坚持定时器的值加倍并重启。坚持计数器最大只能增加到约60秒,在此之后,每次收到零窗口通知,坚持计数器的值就定位60秒。

    2. 对方在收到探测报文段后,在对该报文段的确认中给出现在的窗口值,如果窗口不为零,那么死锁的僵局就被打破了。

    3. 该探测报文发出后,会同时启动重传定时器,如果重传定时器的时间到期,还没有收到接收到发来的响应,则超时重传探测报文。

    6.3.3 保活定时器

    保活定时器是为了应对两个TCP连接间出现长时间的没有数据传输的情况。如果客户已与服务器建立了TCP连接,但后来客户端主机突然故障,则服务器就不能再收到客户端发来的数据了,而服务器肯定不能这样永久地等下去,保活定时器就是用来解决这个问题的。服务器每收到一次客户端的数据,就重新设置保活定时器,通常为2小时,如果2小时没有收到客户端的数据,服务端就发送一个探测报文,以后每隔75秒发送一次,如果连续发送10次探测报文段后仍没有收到客户端的响应,服务器就认为客户端出现了故障,就可以终止这个连接。

    #### 6.3.4 2MSL定时器

    2MSL定时器测量一个连接处于TIME—WAIT黄台的时间,通常为2MSL(报文段寿命的两倍)。2MSL定时器的设置主要是为了确保发送的最后一个ACK报文段能够到达对方,并防止之前与本连接有关的由于延迟等原因而导致已失效的报文被误判为有效。

    6.4 TCP 滑动窗口

    窗口是缓存的一部分,用来暂时存放字节流。发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小。

    发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。

    接收窗口只会对窗口内最后一个按序到达的字节进行确认,例如接收窗口已经收到的字节为 {31, 34, 35},其中 {31} 按序到达,而 {34, 35} 就不是,因此只对字节 31 进行确认。发送方得到一个字节的确认之后,就知道这个字节之前的所有字节都已经被接收。

    6.5 TCP 流量控制

    一般来说,我们总是希望数据传输的更快一些,但如果发送方把数据发送的很快,而接收方来不及接收,这就可能造成数据的丢失。流量控制就是让发送方的发送速率不要太快,让接收方来得及接收。

    接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。

    6.6 TCP 拥塞控制

    如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度

    TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复

    名词

    rwnd	滑动窗口
    cwnd 拥塞窗口
    ssthresh 慢启动门限
    MMS 最大报文段
    RRT 往返时间
    

    发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口。

    为了便于讨论,做如下假设:

    接收方有足够大的接收缓存,因此不会发生流量控制;
    虽然 TCP 的窗口基于字节,但是这里设窗口的大小单位为报文段。

    1. 慢开始与拥塞避免

    发送的最初执行慢开始,令 cwnd = 1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 …(*慢启动, cwnd = 2)

    注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。(当cwnd < ssthresh时,*2,否则 +1 )

    如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。

    1. 快重传与快恢复

    快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认(重复发送对前面有序部分的确认),而不是等待自己发送数据时才进行稍待确认,也不是累积收到的报文发送累积确认,如果发送方连续收到三个重复确认,就应该立即重传对方未收到的报文段(有收到重复确认,说明后面的报文段都送达了,只有中间丢失的报文段没送达)。

    在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如已经接收到 M1 和 M2,此时收到 M4,应当发送对 M2 的确认。
    在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M2,则 M3 丢失,立即重传 M3。
    在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。

    慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。


    问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
    答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

    问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

    1. 为了保证A发送的最后一个ACK报文段能够到达B。该ACK报文段很有可能丢失,因而使处于在LAST—ACK状态的B收不到对已发送的FIN+ACK报文段的确认,B可能会重传这个FIN+ACK报文段,而A就在这2MSL时间内收到这个重传的FIN+ACK报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入CLOSED状态。如果A在TIME—WAIT状态不等待一段时间就直接释放连接,到CLOSED状态,那么久无法收到B重传的FIN+ACK报文段,也就不会再发送一次确认ACK报文段,B就无法正常进入CLOSED状态。
       2. 防止已失效的请求连接出现在本连接中。在连接处于2MSL等待时,任何迟到的报文段将被丢弃,因为处于2MSL等待的、由该插口(插口是IP和端口对的意思,socket)定义的连接在这段时间内将不能被再用,这样就可以使下一个新的连接中不会出现这种旧的连接之前延迟的报文段。

    补充:
       当客户端执行主动关闭并进入TIME—WAIT是正常的,服务端执行被动关闭,不会进入TIME—WAIT状态,这说明,如果终止了一个客户程序,并立即重启该客户程序,则新的客户程序将不再重用相同的本地端口,而是使用新的端口,这不会带来什么问题,因为客户端使用本地端口,而并不关心这个端口是多少。但对于服务器来说,情况就不同了,服务器总是用我们熟知的端口,那么在2MSL时间内,重启服务器就会出错,为了避免这个错误,服务器给出了一个平静时间的概念,这是说在2MSL时间内,虽然可以重新启动服务器,但是这个服务器还是要平静的等待2MSL时间的过去才能进行下一次连接。

    问题三】TCP和UDP的优缺点及区别

    TCP的优点: 可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。

    TCP的缺点: 慢,效率低,占用系统资源高,易被攻击 TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。

    UDP的优点: 快,比TCP稍安全 UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击

    UDP的缺点: 不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。 基于上面的优缺点,那么: 什么时候应该使用TCP: 当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。 在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输

    什么时候应该使用UDP: 当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。 比如,日常生活中,常见使用UDP协议的应用如下: QQ语音 QQ视频 TFTP ……

    有些应用场景对可靠性要求不高会用到UPD,比如长视频,要求速率

    TCP与UDP的区别

    1. 基于连接与无连接;
    2. 对系统资源的要求(TCP较多,UDP少);
    3. UDP程序结构较简单;
    4. 流模式与数据报模式 ;
    5. TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

    问题四】 为什么一定要进行三次握手?

    前两次的握手很显然是必须的,主要是最后一次,即客户端收到服务端发来的确认后为什么还要想服务端再发送一次确认呢?这主要是为了防止已失效的请求报文段突然又传送到了服务端而产生连接的误判。
    考虑如下的情况:客户端发送了一个连接请求报文段到服务端,但是在某些网络节点上长时间滞留了,而后客户端又超时重发了一个连接请求报文段该服务端,而后正常建立连接,数据传输完毕,并释放了连接。如果这时候第一次发送的请求报文段延迟了一段时间后,又到了服务端,很显然,这本是一个早已失效的报文段,但是服务端收到后会误以为客户端又发出了一次连接请求,于是向客户端发出确认报文段,并同意建立连接。假设不采用三次握手,这时服务端只要发送了确认,新的连接就建立了,但由于客户端比你更没有发出建立连接的请求,因此不会理会服务端的确认,也不会向服务端发送数据,而服务端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务端就会一直等待下去,直到超出保活计数器的设定值,而将客户端判定为出了问题,才会关闭这个连接。这样就浪费了很多服务器的资源。而如果采用三次握手,客户端就不会向服务端发出确认,服务端由于收不到确认,就知道客户端没有要求建立连接,从而不建立该连接。

    展开全文
  • 网络中传输层协议

    千次阅读 2020-10-26 11:37:00
    网络传输层协议传输层:UDP:无连接:不可靠:面向数据报:TCP:面向连接:可靠:字节流:常见面试题: 传输层: 传输层主要是负责应用程序之间的数据传输,传输层主要的协议有TCP和UDP UDP: UDP:无连接、不可靠、...

    传输层:

    传输层主要是负责应用程序之间的数据传输,传输层主要的协议有TCP和UDP

    (一)UDP:

    UDP:无连接、不可靠、面向数据报的传输

    UDP的协议格式:
    在这里插入图片描述

    1. 16位的源端口/16位的目的端口:描述数据从哪个进程发送到哪个进程 – 负责实现应用程序间的数据传输
    2. 16位的数据报长度:包含UDP报文头部在内的整体报文长度,16位存储的最大数字为65535
    3. 16位的校验和:二进制反码求和算法,用于校验接收到的数据和发送的数据是否一致
      发送方在发送数据之前,校验和为0,从完整报文的第0个字节开始,每个字节进行取反相加,超过16位的部分取出来,再次与低16位进行相加,最后得到一个校验和填充到协议字段中
      接收方接收到数据之后,从完整报文的第0个字节开始,每个字节进行取反相加,最终的结果如果为0,则表示数据一致,否则则表示数据不一致

    1.无连接:

    无连接是指通信的时候不需要建立连接,只需要知道对方的地址信息,就可以发送数据

    2.不可靠:

    不可靠是指在通信中并不保证数据安全可靠以及有序的到达对方

    3.面向数据报:

    面向数据报是指在UDP传输时,对于上层协议传过来的数据既不合并也不拆分,直接添加上一个UDP头部就开始传输

    面向数据报:无连接、不可靠、有最大传输长度限制的一种传输方式,一个完整的udp报文的总长度不能超过64k(由UDP头部中的数据长度决定)

    1. 影响1:若sendto传输的数据长度大于64k-8,则传输会报错,因此数据过长,需要程序员在应用层自己手动将大数据分割成一个个小的数据段(<64k-8)进行sendto发送
    2. 影响2:但是因为udp并不保证数据有序到达,这时候在上层,程序员进行数据分包之后,就要考虑在应用层实现各个数据段的包序管理
    3. 影响3:udp报文都是整条收发的;因为udp报文头部中定义了报文长度,因此sendto发送数据的时候,数据一到发送缓冲区就会直接封装udp报文头部,然后发送数据(udp的socket发送缓冲区形同虚设,因为并没有起到数据缓冲的作用),接收方接收到数据,放到接收缓冲区中,用户recvfrom接收的时候不会出现接收到半条数据(接收半条头部就没了,就不知道接收多少数据了)或者两条数据的情况,只能是一条完整的数据
    4. 影响4:udp使用recvfrom获取数据的时候,给的buffer要足够大,防止出现数据过长给的buffer不够而报错,接收失败的情况

    (二)TCP:

    TCP是有连接的可靠的面向字节流的传输
    TCP的协议格式:

    在这里插入图片描述

    1. 16位的源端口和目的端口:负责应用程序之间的数据传输
    2. 32位序号/32位确认序号:实现确认应答机制以及接收端的包序管理
    3. 4位头部长度:表示TCP头部有多少,TCP头部是不定长的,主要取决于选项数据的大小,TCP头部最小为20字节,最大60字节(选项数据中占0~40字节)
    4. 6位保留位:目前没有想好用来干什么,先预留出来用于以后扩展
    5. 6位标志位:URG/ACK/PSH/RST/SYN/FIN
    6. 16位窗口大小:表示本端可以接收的数据大小,用于实现滑动窗口机制,进行流量控制
    7. 16位校验和:二进制反码求和算法,校验数据接收与发送的一致性
    8. 16位紧急指针:标识哪些数据是紧急数据(带外数据)
    9. 0-40字节的选项数据:通常用于协商一些信息如MSS的长度

    1.面向连接:

    面向连接指的是在双方进行通信之前需要先建立连接,建立连接后系统就会创建一些数据结构以及资源来维护这些连接,在通信结束后,需要断开连接
    监听套接字只有一个,处于LISTEN状态,用于监听新的连接的到来
    处于ESTABLISHED状态的套接字都是链接套接字

    1. 三次握手建立连接:
      在这里插入图片描述

    2. 四次挥手断开连接:
      在这里插入图片描述

    2.可靠:

    TCP的可靠主要是使得数据能够有序并且安全不丢包的到达对端
    有序是通过协议中的序号来管理包序
    安全则是通过确认应答、超时重传、流量控制、拥塞控制、以及校验字段来实现

    1. 确认应答机制:对于发送的每一条数据都要求接收方进行确认回复(通过TCP头部中的确认号以及ACK标志来实现)

    2. 超时重传机制:在指定时间内没有收到确认回复,则认为数据丢失,对之前的数据进行重传

    3. 协议字段中的序号和确认序号:进行包序管理,并且实现确认应答机制

    4. 确认序号:告诉发送方这个确认序号之前的数据都已经收到,下次发送数据从该序号开始发送----如果第一条数据丢失,就算收到第二条也不会回复,因为每一条回复表示的含义都是前面的数据全部收到了,这种方式可以避免因为ack确认回复的丢失而导致的重传—效率就变高了,如果没有这个确认号,连续发送几个数据后,已经收到了数据,但是ACK回复丢失了,对方也要给你重新发送数据

    5. 协议字段中的校验和:检验数据是否一致,不一致则要求对方重传
      哪一条数据不一致则回复这条数据的起始序号,比如:1~1024数据不一致,就回复确认序号1,要求对方重传1起始的数据

    6. 滑动窗口机制:通过滑动窗口就可以实现数据的连续发送以及进行流量控制,避免发送数据过多而导致丢包。

      通过协议字段中的接收窗口大小实现—通过窗口大小告诉对方最多发送多少数据,避免因为发送数据过多,接收缓冲区溢出,导致丢包
      在三次握手的时候,通信双方会通过选项数据协商一个信息—MSS 最大数据段大小(不包含头部);TCP发送数据的时候,会从发送缓冲区中取出不大于MSS大小的数据封装TCP头部进行发送。
      窗口大小通常不大于接收方的接收缓冲区的剩余空间大小

    7. 拥塞控制机制:滑动窗口实现一次连续发送多条数据,但是网络不好,一开始在网络状态不明的情况下,有可能因为网络情况,导致发的越多丢时的越多-----因此在发送数据时,进行网络探测,查看网络是否能够支持数据的连续快速传输
      实现的原理:慢启动、快增长,通过拥塞窗口实现,拥塞窗口刚开始进入网络是设置为1MSS大小
      在这里插入图片描述

    8. 快速重传机制:提高传输性能----不用等待超时,然后重传。
      发送方连续发送多条数据时,若接收方首先接收到了第二条数据,则有理由认为第一条数据丢失了,因此开始连续发送三条第一条数据的确认请求,发送方接收到连续三次重传请求,则会对这条数据进行重传。三次的原因:有可能前面的数据只是延迟了,而并非丢失了,三条重传请求之间就可以有一个缓冲时间,这个时间内若收到了第一条数据,三次重传请求没有发送完,则发送端就可以不用重传了

      重传这里存在三种协议:停止等待协议/选择重传协议/回退n步协议—属于滑动窗口中的协议

      1. 停止等待协议:滑动窗口没有什么意义,收到第一条回复才会发送第二条数据—适用于网 络状况特别差的场景
      2. 选择重传协议:哪条丢了就重传哪条
      3. 回退n步协议:从丢失的那条数据开始把后面的数据都重新发一次
        在这里插入图片描述
    9. 提高效率的机制:
      1. 延迟应答机制:因为接收方若接收到数据之后立即回复,则窗口大小会变小,传输吞吐率就会降低,因此接收方使用延迟应答机制,延迟一段时间再确认回复,因为在延迟的这段时间内,数据就可能被用户取出,保证传输吞吐率
      2. 捎带应答机制:因为每一条确认回复,都是一个确认回复序号,但是为了确认回复都必须组织一个tcp数据包发送给对端,就会造成大量的空包发送,若接收方即将发送一条数据给对端,则可以在这条即将发送的数据包头中对上一条数据进行确认回复,节省了一个空报头的传输

    总结:

    1. 可靠传输的实现:面向连接/确认应答机制/超时重传机制/序号/确认序号/校验和
    2. 避免丢包:滑动窗口机制/拥塞避免机制
    3. 提高性能:快速重传机制/延迟应答机制/捎带应答机制

    3.字节流:

    字节流传输指的是数据可以在缓冲区中进行堆积,用户取数据的时候就从缓冲区里面想取多少可以取多少,以字节为单位,比较灵活
    发送缓冲区中有很多数据,tcp就会根据mss取出合适大小的数据进行传输,
    接收缓冲区中有很多数据,tcp也可以灵活的以用户需要的大小向上交付

    数据在缓冲区堆积有一个TCP粘包的问题:将多条数据当作一条数据来处理

    粘包的本质原因:tcp在传输层对数据边界不敏感(不管上层数据是什么样的,每次都根据mss取出合适大小进行发送/不管接收缓冲区中是什么数据,只管从缓冲区中取出用户需要的大小的数据),因此造成了粘包的问题
    粘包的解决方案程序员在应用层进行数据的边界管理

    1. 特殊字符进行间隔 ---- 每条数据结尾有个特殊字符作为结尾,但是我们传送的数据中也有可能有这个字符
    2. 数据定长 ---- 每次只发送/接收指定长度的数据,数据短了造成大量的资源浪费
    3. 在应用头部中定义数据长度字段 ---- 先按照指定长度将头部获取,根据头部中的长度,取出指定长度的数据(类似UDP) ----最典型的就是http中,用\r\n间隔,头部中Content-Length定义正文的长度

    (三)常见面试题:

    1. 握手为什么是三次?两次不安全/四次没必要
      Tcp是双向通信,必须确保双方都具有数据收发的能力;假设客户端发送请求连接后直接退出了,因此都要给对方发送SYN请求

    2. 握手失败服务端是怎么处理的?
      主要是第二次的握手过程失败—若服务端回复ACK+FIN后迟迟得不到ACK回复,则服务端会发送RST重置连接报文,然后销毁socket
      SYN泛洪攻击:恶意主机,不断的发送SYN请求给服务器,但是不进行最后一个ACK回复—消耗服务器的连接资源

    3. 挥手为什么是四次?
      发送FIN包只能表示不再给对方发送数据,不代表不再接收数据,因此被动关闭方对FIN确认回复后,依然有可能要发送数据,主动关闭方可能还会接收数据,正因如此,被动关闭方不能把ACK与FIN合成一个数据报进行发送(但是有可能刚好被动关闭方也要关闭连接,所以四次挥手也可能是三次挥手)

    4. 主动关闭方的TIME_WAIT状态有什么用?–用来保护主动关闭方,避免立即使用相同的地址信息对后续通信造成影响
      假如没有TIME_WAIT状态会出现什么情况:主动关闭方直接释放socket,意味着端口和地址可以立即重新使用,若最后一次主动关闭方ACK丢失,等待超时后被动关闭方就会重传一个FIN包,假如主动关闭方主机释放之后立即使用了刚才套接字的端口和地址信息重新启动了程序,1.新的程序使用原先的地址信息与对方通信,就收到了这个重传的FIN包2.新的程序使用原先的地址信息连接相同的服务器,而这个服务器正在等待最后一次ACK,而这次连接给建立时给服务器发送的是一个SYN请求连接包 ----------- 如果主动关闭方没有TIME_WAIT直接释放资源,新程序就有可能立即使用了上一次相同的地址信息,上一次的通信就可能会对新建的通信造成影响,因此主动关闭方必须等待一段时间—(2MSL—两个报文的最大生存周期),能够处理被动关闭方可能重传的FIN包,并且等待本次通信的所有数据都消失在网络中,避免对后续连接造成影响,

    5. 一个主机上出现了大量的CLOSE_WAIT是什么原因?
      证明你的代码有问题,连接断开后没有close关闭套接字释放资源

    6. 一个主机上出现了大量的TIME_WAIT是什么原因?
      TIME_WAIT是主动关闭方才会有的状态,常出现于爬虫服务器,大量的主动关闭了连接
      地址重用 / 缩短TIME_WAIT等待时间

    7. TCP连接管理中的保活机制:tcp协议是面向连接的,若通信双方长时间没有数据往来,就需要确定对方还是否在线,连接是否正常,若通信双方长时间(7500s)没有数据往来,则服务端会每隔一段时间(75s)向客户端发送一个保活探测数据包,要求对方响应,若多次(9次)无响应,则认为连接断开(可以配置—通过设置套接字选项—setsockopt)
      连接断开对上层程序编写的影响:被动关闭端recv返回0,关闭端send触发异常

    8. recv的原理:操作系统把网卡接收的数据放到对应socket的接收缓冲区中,然后通过就绪描述符找到socket,然后从接收缓冲区中取出想要的大小的数据
      send就是将想要发送的数据放到发送缓冲区中,tcp会从缓冲区中取出合适大小的数据进行数据封装然后发送

    9. UDP粘包怎么解决:UDP不会产生粘包,因为UDP是整条收发的,而且UDP的头部中还有数据的长度

    10. Tcp协议和udp协议有什么区别:
      1.TCP是面向连接的,UDP是不面向连接的……
      2.TCP是可靠的,UDP是不可靠的……
      3.TCP是面向字节流的UDP是面向数据报的……
      Udp速度快,但是不可靠,tcp是可靠的传输但是速度相对慢,而且用到的资源也比较多

    11. UDP怎么实现可靠传输?
      先回答TCP实现可靠传输的机制,然后说把TCP实现可靠的机制拿到UDP的应用层中就可以实现UDP的可靠传输

    展开全文
  • ssh传输层协议

    千次阅读 2018-01-24 19:13:45
    环境纯理论知识,只是笔记,非教程二进制协议格式每个数据包为以下格式: 类型 名称 uint32 packet_length byte padding_length byte[n1] payload; n1=packet_length-padding_length-1 byte[n2] random ...

    环境

    纯理论知识,只是笔记,非教程

    二进制协议格式

    每个数据包为以下格式:

    类型名称
    uint32packet_length
    bytepadding_length
    byte[n1]payload; n1=packet_length-padding_length-1
    byte[n2]random padding; n2=padding_length
    byte[m]mac(Message Authentication Code - MAC);m=mac_length

    协议过程

    协议版本交换

    当 TCP 连接建立后,双方都必须发送一个标识字符。该标识字串必须是:

    SSH-protoversion-softwareversion SP comments CR LF
    
    # 我公司的服务器返回的信息
    SSH-2.0-OpenSSH_5.3
    名称描述
    protoversion协议版本
    softwareversion软件版本
    SP空格
    comments可选字符串
    CR回车
    LF换行

    算法协商

    密钥交换从每一方发送如下数据包开始:

    类型名称
    byteSSH_MSG_KEXINIT
    byte[16]cookie (random bytes)
    name-listkex_algorithms
    name-listserver_host_key_algorithms
    name-listencryption_algorithms_client_to_server
    name-listencryption_algorithms_server_to_client
    name-listmac_algorithms_client_to_server
    name-listmac_algorithms_server_to_client
    name-listcompression_algorithms_client_to_server
    name-listcompression_algorithms_server_to_client
    name-listlanguages_client_to_server
    name-listlanguages_server_to_client
    booleanfirst_kex_packet_follows
    uint320 (为将来扩展预留)
    byte        SSH_MSG_KEXINIT
    byte[16]    cookie (random bytes)
    name-list   kex_algorithms
    name-list   server_host_key_algorithms
    name-list   encryption_algorithms_client_to_server
    name-list   encryption_algorithms_server_to_client
    name-list   mac_algorithms_client_to_server
    name-list   mac_algorithms_server_to_client
    name-list   compression_algorithms_client_to_server
    name-list   compression_algorithms_server_to_client
    name-list   languages_client_to_server
    name-list   languages_server_to_client
    boolean     first_kex_packet_follows
    uint32      0 (为将来扩展预留)

    cookie:必须是一个由发送方生成的随机值。它的作用是使任何一方都不可能对密钥和会话标识符拥有完全决定权。

    kex_algorithms: 密钥交换算法。列表的话,用逗号(,)隔开

    server_host_key_algorithms: 受支持的为服务器主机密钥服务的算法的名称列表,按优先级排序。通俗点说就是服务器所支持的算法列表,用逗号(,)隔开

    encryption_algorithms: 可接受的对称加密算法(也称为加密器)的名称列表,按优先级排序。

    mac_algorithms: 可接受的 MAC 算法的名称列表,按优先级排序。

    compression_algorithms: 可接受的压缩算法的名称列表,按优先级排序。

    languages: 语言标志的名称列表,按优先级排序。

    first_kex_packet_follows: 表明是否有一个猜测的密钥交换数据包跟随。

    Diffie-Hellman 密钥交换

    首先,客户端发送:

    byte    SSH_MSG_KEXDH_INIT
    mpint   e

    服务器响应如下:

    byte    SSH_MSG_KEXDH_REPLY
    string  K_S,服务器公钥和证书 (
    mpint   f
    string  s,对 H 的签名

    密钥交换在每一方发送一个 SSH_MSG_NEWKEYS 消息后结束

    byte    SSH_MSG_NEWKEYS

    参考地址:

    ssh 协议:SSH 传输层协议

    展开全文
  • 计算机网络:传输层协议TCP详解

    千次阅读 2019-06-17 01:47:10
    TCP协议作为传输层协议,它在网络层IP协议不可靠的尽力而为服务至上提供了一个可靠数据传输服务。TCP协议的数据传输确保了其上层协议读出的数据是无损坏、无间隔、按序、非冗余的二进制流。 TCP是面向连接的,在两个...

    概述

    TCP协议作为传输层协议,它在网络层IP协议不可靠的尽力而为服务至上提供了一个可靠数据传输服务。TCP协议的数据传输确保了其上层协议读出的数据是无损坏、无间隔、按序、非冗余的二进制流

    TCP是面向连接的,在两个进程通过TCP协议发送数据时,必须先要经过互相“握手”,来建立确保数据传输的参数。TCP连接不是在电路交换网络中的端到端TDM或者FDM电路,也不是构建在网络层上的虚电路,所以中间的网络元素并不会维持TCP的连接状态,对于路由器而言,它们所看到的只是一个IP数据报文,而不是连接。

    TCP连接提供全双工服务,也就是说进程A与进程B存在一条TCP连接时,在同一时间内,它们都是可以互相发送数据的。并且,TCP是一个点对点数据传输的协议,即不支持多播


    报文结构

    TCP报文由首部字段数据字段组成:

    TCP报文长度并不是无限的,它受限于所谓的最大报文段长度(Maximum Segment Size, MSS),简称MSS,MSS和什么有关呢?
    一般来说,MSS根据最初确定的由本地发送主机的最大链路层帧长度(Maximum Transmission Unit, MTU),简称MTU来设置,设置MSS需要保证一个TCP报文加上网络层IP协议的首部长度(40字节)将适合底层的单个链路层帧。在链路层协议中,以太网和PPP协议都具有1500字节的MTU,所以用MTU减去IP协议首部长度字段就可以得到MSS的典型值1460字节

    从上面这张图我们可以看到TCP首部字段至少有20个字节。在开头,和UDP协议类似,都有2个字节的源端口号字段和2字节的目的端口号字段,也包含用于校验数据正确性的检验和字段。除此之外,它还包含以下几个字段:

    • 4字节的序号字段和4字节的确认号字段:这些字段用于被TCP发送方和接收方实现可靠的数据传输。其中,序号字段用来解决包乱序的问题,确认号用于解决丢包问题。
    • 2字节的接收窗口字段:用于实现流量控制,该字段用于指示接收方愿意接收的字节数量,也就是可以控制发送窗口或者接收窗口的大小(我们待会会提到)。
    • 4比特的首部字段长度,该字段指示了以4字节为单位的TCP首部长度,因为TCP首部的长度是可变的(因为选项字段是可变的)
    • 6比特标志字段:用于操作TCP状态机。6个比特中每个比特依次是:URG、ACK、PSH、RST、SYN、FIN。ACK比特用于确认报文,即向报文发送方确认该报文段已经成功送达。RST、SYN、FIN用于TCP连接建立(三次握手)与TCP连接解除(四次挥手)。PSH比特用于指示接收方应立刻将数据交付上层协议。URG比特用来指示报文段里存在着被发送端上层实体置为紧急的数据,紧急数据的最后一个字节由2字节的紧急数据指针制定出(在实践中,URG、PSH很少被采用)

    序号字段确认号是TCP协议实现可靠传输的关键字段。TCP把数据看成是一个无结构、有序的字节流(而不是像UDP那样把把数据看成是一整个包),序号字段也就是建立在传输的字节流上,即序号应当对应于该报文段首字节的字节流编号。确认号比序号稍复杂些,由于TCP是全双工协议,因此进程A在向进程B发送数据时也需要接收进程B传来的数据,进程A填充进报文段的确认号是进程A期望从进程B收到的下一个字节的序号。通过上述这个机制,TCP就可以建立起一个可靠的连接,我们举几个例子:

    • 假设进程A已经收到了进程B传来的编号为0~1000字节的数据,那么进程B会发送一个ACK,并将确认号设置为1001,表示期望接收到序号为1001的TCP数据包。
    • 假设进程A收到了进程B传来的编号为0~1000的数据,也收到了2000~3000的数据,但是1001~1999的数据在这两者之后才收到(也就是数据的乱序到达),这时,TCP的处理方式是保留失序的字节,等待缺少的字节到达后填补空隙。

    我们待会会仔细介绍上述例子的具体实现原理。


    TCP连接的建立、解除

    连接的建立

    TCP连接的建立需要经历三次握手的过程:

    步骤如下:

    1. 客户端向服务器发送一个TCP报文:SYN比特标记为1,序号取一个任意值x。此时,客户端进入SYN_SENT状态。
    2. 服务器收到该SYN报文后,向客户端发送一个ACKTCP报文:SYN比特标记为1,序号再取一个任意值y,并将确认号设为x + 1,并将其发送给客户端。服务器进入SYN_RCVD状态。
    3. 客户端向服务器发送一个TCP报文:将确认号设为y + 1。然后客户端进入ESTABLISHED状态。
    4. 服务器收到该报文后,同样进入ESTABLISHED状态。

    为什么TCP的连接建立过程需要三次握手?
    因为服务器和客户端都需要知道对方的接收消息功能和发送消息功能是正常的

    • 如果连接建立只需要一次握手,那么客户端无法获知服务端是否能够接收消息或者发送分组。在这种情况下,客户端向服务器发送了一个SYN包,然后建立连接。如果仅仅是这样,客户端根本无法知道服务器是否收到了这个请求。

    • 如果连接建立需要两次握手,那么客户端可以获知服务端的接收和发送分组的功能是正常的,但是服务端只能够知道客户端发送分组的功能是正常的,无法获知接收报文的功能是否正常。

    • 当连接需要三次握手时,服务端就可以获知客户端发送和接收报文的功能是正常的。所以通过三次握手就可以建立连接了。

    • 至于为什么不是四次握手,因为没有必要,在三次握手的情况下就已经可以让服务器和客户端知道对方的接收消息功能和发送消息功能是正常的。

    连接的解除

    TCP连接的解除需要经历四次挥手过程:

    我们设定:主动断开方为客户端,被动断开方为服务器
    步骤如下:

    1. 客户端向服务器发送一个TCP报文:FIN比特设为1,序号设为x,确认号设为y(注意,这里的xy和连接建立时不同)。客户端进入FIN_WAIT_1状态。
    2. 服务器向客户端发送一个ACKTCP报文:确认号设置为x + 1。服务器进入CLOSE_WAIT状态,客户端收到报文后进入FIN_WAIT_2状态。
    3. 服务器向客户端发送一个TCP报文:FIN比特设为1,序号设为y。服务器进入LAST_ACK状态,客户端收到报文后进入TIME_WAIT状态。
    4. 客户端向服务器发送一个TCP报文:确认号设为y + 2

    其实你仔细看就会发现,可以将四次挥手拆分为两个部分:客户端的挥手和服务端的挥手,因为它们都有个共同特征就是先发送了FIN报文然后再接收ACK报文。之所以这么设计是因为TCP是全双工的协议,因为FIN报文就代表自己的数据已经发送完毕了,但这个时候还是可以接收来自对方的数据的。当对方也没有数据要发送时,也需要主动发送一个FIN报文,然后再接收对方的ACK,最后愉快地断开连接。同时这也是为什么TCP挥手需要四次。

    主动关闭TCP连接的端系统在完成四次挥手后需要进入TIME_WAIT状态,时长2MSLTIME_WAIT主要作用为:

    • 可靠地实现TCP连接的终止
      在四次挥手的最后阶段,无法保证ACK包一定发送到了被动关闭方,所以需要将该TCP连接维持一段时间,保证被动关闭方再次发送FIN包时能够将ACK包发送给被动关闭方。
    • 允许老的重复分组在网络中消逝
      TCP分组可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分组,迷途的分组在路由器修复后也会被送到最终目的地。如果不维持TIME_WAIT状态,那么系统会复用这个端口,然后该分组发送到目的地后会被误解。

    在Linux系统中,解决大量TIME_WAIT的方法有:

    • 设置参数net.ipv4.tcp_tw_reuse = 1 表示允许将TIME_WAIT套接字用于新的连接。
    • net.ipv4.tcp_tw_recycle = 1 表示开启TCP中TIME_WAIT的快速回收。

    重传机制

    TCP若需要保证所有的数据包都能够正确地抵达,必须要有一个重传的机制。那么什么时候会发生重传呢,有以下几种情况:

    1、数据包发生了丢包

    在上图中,进程A在发送SEQ=21的数据包(数据长度为11字节)后,由于网络故障发生了掉包。此时对于进程A来说最直观的感受就是迟迟没有收到来自进程B的ACK包。当超过一定的时间后,进程A就会重新尝试发送SEQ=21的数据包,直到收到进程B的ACK包。

    丢包重传的效率在于超时时间的设置是否合理,如果超时时间太长,那么显而易见的效果就是会严重影响传输性能。如果超时时间太短,可能会导致并没有发生丢包就进行了重传,严重的可能会产生网络拥塞,增加数据包的时延。

    首先这个超时时间肯定不能设置为一个恒定的值,因为受限于物理、网络设备等影响,往返时间(RTT) 肯定是有所差异的。例如从上海到北京的RTT肯定要比从上海到美国的RTT短。

    那么这个超时时间是如何设置的呢,这涉及到了TCP的RTT算法
    RTT算法实现有很多种,例如RFC793定义的经典算法,Karn / Partridge算法、Jacobson / Karels算法等。这里我们只简单提下RFC793的经典算法,其它算法有兴趣的可以自行Google。
    算法的实现步骤如下:

    1. 先进行RTT的采样,我们定义采样得到的值为Sample RTT。当然,任何一个采样获取的Sample RTT是非典型的,所以自然要采取一个对Sample RTT取平均值的一个算法,我们称这个平均值为Estimated RTT,一旦获取到一个新的Sample RTT,该算法就会通过以下计算方法来更新Estimated RTT的值:
                 E s t i m a t e d R T T = ( 1 − α ) × ( E s t i m a t e d R T T ) + α × S a m p l e R T T EstimatedRTT=(1-α) \times (EstimatedRTT)+α \times SampleRTT EstimatedRTT=(1α)×(EstimatedRTT)+α×SampleRTT
      在RFC6298中,给出的α参考值是0.125。
    2. 初此之外,还需要计算RTT偏差,即Dev RTT,用于估算Sample RTTEstimated RTT的偏离程度:
                 D e v R T T = ( 1 − β ) × D e v R T T + β × ∣ S a m p l e R T T − E s t i m a t e d R T T ∣ DevRTT=(1-β) \times DevRTT +β \times |SampleRTT-EstimatedRTT| DevRTT=(1β)×DevRTT+β×SampleRTTEstimatedRTT
      其中,β的推荐值为0.25。
    3. 得出Estimated RTTDev RTT的值后,首先需要肯定的是超时时间肯定需要大于Estimated RTT,否则将会造成不必要重传,然后肯定也不能大太多,否则当报文发生丢失时,TCP将不能及时重传报文段。因此需要将Estimated RTT加上一点余量,所以实际设置的超时时间TimeoutInterval为:
                 T i m e o u t I n t e r v a l = E s t i m a t e d R T T + 4 × D e v R T T TimeoutInterval=EstimatedRTT+4 \times DevRTT TimeoutInterval=EstimatedRTT+4×DevRTT
      推荐的初始TimeoutInterval为1秒。并且只要Estimated RTT更新了,上述的TimeoutInterval也会立刻得到更新。
    2、ACK包发生了丢包

    还有一种情况可能就是进程A发送的SEQ=21的数据包(数据长度为10字节)已经成功到达进程B的TCP接收窗口,进程B在发送ACK包后,由于网络故障导致ACK包发生了丢包。此时进程A的直观感受等同于数据包发生了丢包,所以同样在超过一定时间后,重新发送SEQ=21的数据包。当进程B收到这个数据包后,会丢弃这段数据(因为事实上已经收到这个包了),然后再次发送一个ACK包,直到进程A收到这个包为止。如下图所述:

    快速重传机制

    在实际情况中,应用程序可能会在应用层协议中组装一个比较大的包,并发送给服务器(例如HTTP协议中的文件上传请求),这个时候TCP协议一般会将其拆分为多个TCP包并依次发送给服务器,现在的情况是,如果其中的一个数据包发生了丢包,而其它数据包成功抵达了服务器,那么TCP协议会如何处理?答案如下图:

    TCP协议引入了一种快速重传机制。它允许在数据包没有连续到达时,就连续发送ACK包(其值为最后那个没有按顺序到达的包)。如果发送方连续三次收到了同样的ACK包,就认定这个包发生了丢包,那么会重传这个丢掉的数据包,当服务器收到后,由于后面的数据包已经正确收到,所以就会发送ACK=6000的包。这么做的好处在于不一定要等到超时再补发缺失的数据包。
    但是快速重传机制依然存在一个问题,就是客户端无法获知这三个ACK=2000的包是不是连续的。在客户端收到三个连续的ACK之前,可能已经连续发送了SEQ=6000SEQ=7000······,也就是意味着客户端端可能需要从SEQ=2000开始,一直重传之后所有发送的数据包。为了解决这个问题,选择确认机制(Selective Acknowledgment)出现了。

    选择确认机制

    选择确认机制需要在TCP报文头(TCP选项中)中引入一个SACK字段,它使得接收方能告诉发送方哪些报文段丢失,哪些报文段重传了,哪些报文段已经提前收到等信息。根据这些信息TCP就可以只重传哪些真正丢失的报文段。需要注意的是只有收到失序的分组时才会可能会发送SACK,TCP的ACK还是建立在累积确认的基础上的。也就是说如果收到的报文段与期望收到的报文段的序号相同就会发送累积的ACK,SACK只是针对失序到达的报文段的。

    此外,TCP还可以处理丢包现象。TCP协议采用了超时重传的机制来处理报文段的丢失。关于超时时间具体是如何计算的,可以参考这篇博客

    需要注意的一点是,序号不一定非要以0开始,这么做可以减少仍在网络中存在的来自两台主机之间先前已经终止的连接报文段,被误认为师后来两台主机之间新建的TCP连接所产生的报文的可能性。

    TCP发送方有三个与发送和重传相关的事件:

    • 从上层应用程序收到数据。该事件发生时,TCP会将应用程序报文封装到符合TCP协议的报文中,然后交付给网络层的IP协议。当报文段传送给IP协议时,TCP就启动定时器确保数据能够在超时后重传。
    • 超时。当定时器超过超时阈值的时候,就进行数据的重传。
    • 收到ACK。TCP将ACK报文中的确认号提取出来,如果确认号大于SendBase(即最早未被确认的字节的序号),则该ACK是在确认一个或者多个先前未被确认的报文段。

    TCP缓冲区

    之所以TCP协议能像上面例子那样能够解决数据的乱序到达和丢包问题,是因为在TCP连接中,两个进程都各自维护了一个发送缓冲区和接收缓冲区。
    发送缓冲区
    在这里插入图片描述
    发送缓冲区将其中的数据分为了四种类型:

    • 已经发送并且成功收到的数据:这些数据都已经得到接收者的ACK应答。
    • 已经发送但未被确认的数据:该数据已经发送但尚未得到接收者的ACK应答,所以该数据仍在发送窗口中,一旦没有及时收到接收者的ACK确认就需要进行重发。
    • 需要尽快发送的数据:该数据已经被加载到窗口中,等待发送。
    • 未发送,也不允许发送数据:该数据没有被发送出去,并且接收端也不允许发送,因为这些数据已经超出了发送端所能够接收的范围。

    接收缓冲区
    在这里插入图片描述
    接收缓冲区分为了三个部分:

    • 已经接受的数据但尚未被上层协议处理
    • 未接收,但准备接收的数据
    • 未被接收并且未准备接收的数据

    上述两个缓冲区还可以用于TCP的拥塞控制


    拥塞控制

    TCP协议除了提供可靠的传输外,也提供了拥塞控制功能。

    何为网络拥塞

    网络拥塞(Network Congestion)是指在分组交换网络中传送分组的数目太多时,由于存储转发节点的资源有限而造成网络传输性能下降的情况。

    为了更加形象的概括,我们假设进程A和进程B对应为城市A,城市B,那么连接两个城市的高速公路就相当于网络链路,数据包就相当于高速公路上的汽车。当城市A有很多汽车需要前往城市B时,高速公路就有很大概率发生堵车,汽车行驶速度下降,也就是数据包的时延增大了。然而在网络传输中,由于IP协议的TTL限制,超过TTL的数据包会被路由器丢弃,也就是说汽车无论如何也到达不了城市B了。所以拥塞控制的关键就是要把握好什么时候要增加、减少TCP数据包发送的大小或者其次数。

    拥塞控制的方法

    因为网络层IP协议是不会向上层协议提供网络拥塞反馈的,所以TCP作为其可靠的传输层协议必须要使用端到端的拥塞控制方法。
    TCP所采用的方法就是让每个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率。也就是说,如果发送方能够感知到路径上没什么拥塞,那么就应当加快传输速率,如果能够感知到有拥塞,那么就应当减少其传输速率。

    那么TCP是如何感知有拥塞呢?当TCP发生了“丢包事件”时,我们就可以认定发生了拥塞。丢包事件包含:

    • 超时的发生
    • 连续收到来自接收方的三个冗余ACK包。

    TCP控制流量的方式是通过连接建立时产生的变量cwnd(拥塞窗口)来计算。
    拥塞控制包含四个部分:慢启动拥塞避免快速重传快速恢复。快速重传刚才已经提到过,这里就不细说了。

    1、慢启动

    慢启动通俗点讲就是在TCP连接刚刚建立时,一步步地提高速度。具体实现步骤如下:

    1. 首先将cwnd设为MSS的一个较小值,也就是说初始发送速率为MSS/RTT
    2. cwnd以1个MSS开始并且每当传输的报文段首次被确认就增加1个MSS。每经过一次RTT,就将发送速率翻一倍。

    那么何时结束这种指数级别的增长呢?有三种方法:

    • 如果存在一个由超时指示的丢包事件,TCP发送方就将cwnd设为1并重新开始慢启动过程。它还将第二个状态变量的值ssthresh(慢启动阈值)设为cwnd的一半,即检测到拥塞时将ssthresh设为拥塞窗口值的一半。
    • 第二种方式是直接与ssthresh相关联,当cwnd等于ssthresh时,结束慢启动并将其转换为拥塞避免模式
    • 第三种方式是如果检测到3个冗余的ACK时,就进行一次快速重传并进入到快速恢复状态。
    2、拥塞避免

    一旦进入到拥塞避免状态,cwnd的值大约是上次遇到拥塞时的一半。TCP此时不会直接将cwnd乘以2去加快速度,而是通过一种线性的方式增加cwnd,即将cwnd的值每次只增加一个MSS。当出现超时后,TCP的拥塞避免算法行为和慢启动一样,将cwnd的值设为一个MSS,当丢包事件出现时,sshresh被更新为cwnd的一半。接下来就是快速恢复阶段。

    3、快速恢复

    快速恢复算法是认为,当发生了三个冗余ACK时说明网络状况并不算那么糟,所以无需像超时那样那么强烈。快速恢复步骤如下:

    1. cwnd设置为sshthresh加上3倍的MSS
    2. 重传冗余ACK指定的数据包。
    3. 如果再次收到冗余ACK,那么将cwnd加上1
    4. 如果收到了新的ACK,那么将cwnd设为sshthresh,然后进入拥塞避免算法。
    总结

    TCP的拥塞控制可以形容为加性增,乘性减的拥塞控制方式。

    展开全文
  • 传输层的主要功能和协议

    万次阅读 2018-04-12 19:56:53
    传输层的主要功能和协议:-传输层位于OSI参考模型正中间,具有承上启下的核心作用,它是OSI中最重要的,最关键的一层,是唯一负责总体的数据传输和数据控制的一层。传输层提供端到端的交换数据的机制,传输层对会话...
  • UDP-无连接的传输层协议-基础知识

    千次阅读 2020-12-03 17:35:01
    传输层协议 UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。但是正因为UDP协议的控制选项较少,在数据传输过程中延迟小、...
  • TCP/IP协议传输层

    千次阅读 2019-05-06 00:04:58
    网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机...传输层协议:TCP UDP 传输层两个协议应用场景 TCP: 传输控制协议 TCP(Transmission Control Protocol)是面向连接的,可靠的流协议; 分段 编...
  • TLS(传输层安全)协议

    千次阅读 2018-11-22 10:47:36
    TLS协议概述 学习了TLS协议的一些基本原理和实现,想将它分享出来,也看看我是否是学到了精髓,我尽量...TLS的前身是安全接口SSL,所以也常写成SSL/TLS关于TLS的发展,我觉得了解一个协议的发展背景和发展历史也...
  • 实验四 应用层和传输层协议分析(PacketTracer) 一、实验目的:  通过本实验,熟悉PacketTracer的使用,学习在PacketTracer中仿真分析应用层和传输层协议,进一步加深对协议工作过程的理解。 二、实验内容...
  • 博文目录一、传输层与传输层协议 二、用户数据报协议(UDP) 三、传输控制协议TCP 四、TCP协议滑动窗口一、传输层与传输层协议1. 传输层的基本功能 传输层的本质就是为分布在不同地理位置的计算机的进程通信提供...
  • 应用层协议: 1、远程登录协议(Telnet) 2、文件传输协议(FTP) 3、超文本传输协议(HTTP) 4、域名服务协议(DNS) 5、简单邮件传输协议(SMTP) 6、邮局协议(POP3)   其中,从网络上...
  • SSL&TLS传输层加密协议实现图解

    千次阅读 2017-09-27 23:03:11
    http://xuding.blog.51cto.com/4890434/1732275 ... Sockets Layer ,加密套接字协议层 ... 1)SSL是为网络通信提供安全及数据完整性的一种安全协议,在传输层对网络连接进行加密  Secure Socket Lay
  • 这篇文章主要介绍了网络协议概述:物理层、连接层、网络层、传输层、应用层详解,本文用生活中的邮差与邮局来帮助理解复杂的网络协议,通俗易懂,文风幽默,是少见的好文章,需要的朋友可以参考下 信号的传输总要符合...
  • IP首部有一个协议字段,用来标识网络层的上一层所采用的是哪一种传输层协议。根据这个字段的协议号,就可以识别IP传输的数据是TCP的内容还是UDP的内容。 TCP/IP的大多数协议都是以客户端/服务器端的形式运行,...
  • 5G核心网传输层HTTP/2协议

    千次阅读 2020-03-27 14:06:32
    5G核心网络传输层统一采用HTTP/2协议,应用层携带不同的服务消息.因为底层的传输方式相同,所有的服务化接口就可以在同一总线上进行传输,这种通信方式又可以理解为总线通信方式,在总线上每个NF通过各自的服务化接口...
  • 网络安全协议 IPsec 我们经常使用的虚拟专用网(某PN),在某PN中传送的信息都是经过加密的,而IPsec就是提供的这个服务。 IPsec并不是一个单一协议,而是能够在IP提供互联网通信安全的协议族。IPsec并没有限定...
  • 传输层协议之TCP和UDP详细说明

    千次阅读 2020-12-16 11:13:20
    传输层 传输层功能介绍 传输层: 标明上层所使用什么样的应用 端口号(2字节) SYN(1bit) ACK(1bit) 传输层的功能: session multiplexing——会话多路复用 Identification of different applications——...
  • TCP/IP  TCP/IP是个协议组,可分为三个层次:网络层、传输层和应用层。  在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP...在传输层中有TCP协议与UDP协议。  在应用层有:TCP包括FTP、HTTP、TELNET、SMT
  • 传输层安全协议TLS/SSL

    千次阅读 2016-08-29 18:14:06
    部分链接可能需要使用Google才能打开描述:传输层安全协议TLS(Transport Layer Security)是设计用来保护网络通信过程中信息的私密性的一种工业标准,允许客户机,服务器应用程序可以探测到安全风险,包括消息篡改...
  • 传输层TCP协议三次握手详解

    千次阅读 2016-11-16 15:17:36
    在TCP,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG. 其中,对于我们日常的分析有用的就是前面的五个字段。 它们的含义是: SYN表示建立连接, FIN表示关闭连接, ACK...
  • 一、TCP/IP通信传输流 TCP/IP协议族按层次分别分为以下4层:应用层、传输层、网络层和数据链路层 1、利用TCP/IP协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则从链路层往上...
  • OSI七层模型详解(物理层、数据链路层、网络层、传输层.....应用层协议与硬件)   OSI 七层模型通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯,因此其最主要的功能就是帮助...
  • 网络体系结构通常是由两种模型来表示,一个是7的OSI参考模型,一个是5的TCP/IP参考模型。 OSI七模型: TCP/IP五模型: TCP/IP模型由于其协议被广为流传,乃至后来被Internet使用,所以我们后面也主要...
  • TCP/IP协议分析(传输层安全缺陷)

    千次阅读 2020-01-12 00:50:03
    传输层向其上的应用层提供通信服务,属于通信部分的最高层,同时也是用户功能中的最低层。只有位于网络边缘的主机才有传输层,网络核心部分的路由器只用到下三层的功能。 传输层为应用进程之间提供端到端的逻辑通信...
  • 目录实验名称实验介绍实验目的背景知识和准备HTTP协议HTTP概述HTTP连接HTTP请求报文HTTP响应报文TCP协议TCP概述i. 端到端ii. 可靠、有序的字节流iii. 流水线iv. 发送和...应用层和传输层网络协议分析 实验介绍 实验使
  • 几种常用的网络传输协议

    千次阅读 2019-10-07 10:36:08
    一、OSI模型 名称            层次           ...物理   &...
  • 信号的传输总要符合一定的协议(protocol)。比如说长城上放狼烟,是因为人们已经预先设定好狼烟这个物理信号代表了“敌人入侵”这一抽象信号。这样一个“狼烟=敌人入侵”就是一个简单的协议协议可以更复杂,比如...
  • HTTP是应用层协议,TCP(传输控制协议)UDP(用户数据协议)他们是传输层协议,IP(网络协议),至于数据链路(就是我们说的以太网,FDDI,令牌环网等)socket是操作系统用来实现网络传输层以下协议的方式。...
  • 传输层详解

    万次阅读 2016-01-06 19:08:05
    传输层详解 ①理解TCP的封装和工作原理 ②理解UDP的封装和工作原理 ③了解常用的TCP和UDP端口号 ④对TCP和UDP首部能够进行分析   传输层的作用是什么?传输层实现端到端的连接,端到端是什么概念呢?打个...
  • 因此,传输层负责提供两节点之间数据的可靠传送,当两节点的联系确定之后,传输层则负责监督工作。综上,传输层的主要功能如下: 传输连接管理:提供建立、维护和拆除传输连接的功能。传输层在网络层的基础上为高层...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 180,848
精华内容 72,339
关键字:

以下属于传输层的协议是