运输层

 一、概述

  (1)OSI七层模型中的物理层、数据链路层和网络层,它们是面向网络通信的低三层协议运输层负责端到端的通信,既是七层模型中负责数据通信的最高层,又是面向网络通信的低三层和面向信息处理的最高三层之间的中间层。运输层位于网络层之上、会话层之下,它利用网络层子系统提供给它的服务去开发本层的功能,并实现本层对会话层的服务。

  (2)运输层负责端到端的通信:通俗的讲,两个主机通讯,也就是应用层上的进程之间的通信,也就是转换为进程和进程之间的通信了。

  (3)IP协议能将分组准确的发送到目的主机,通过IP地址能找到不同网络下的网络,结合mac地址就能找到对应主机,

      那么怎么找到主机应用进程呢,肯定也有一个东西来标识它,那就是我们常说的端口了。

二、端口

  (1)端口,占有16位,其大小也就有65536个,是从0~65535.也就是一台计算机有65535个端口。

      主机之间的通讯,也就是应用进程之间的通讯,都要依靠端口,一个进程对应一个端口。

  (2)端口是标志本计算机应用层中各个进程与运输层交互时的层次接口。不同计算机界相同端口之间无联系。

  (3)端口分类:

      1)熟知端口(系统端口):0-1023

      

      2)登记端口:1024-49151:比如微软开发了一个系统应用,该应用在通讯或使用时,需要使用到xxx端口,那么就要去登记一下这个端口,

                  以免有别人公司的应用使用同一个端口号

      3)客户端端口:49152-65535,又叫短暂端口号,用户进程选择暂时使用,通信结束后,就释放掉。

  (4)运输层就是将两个端口连起来通信的介质,端口怎么使用,怎么通信,靠两个协议,UDP和TCP协议。

三、UDP(User Datagram Protocol)

1、UDP协议全称是用户数据报协议 : 在IP数据报服务之上添加了复用和分用以及差错检测的功能。

2、复用指在发送方不同的应用进程都可以使用同一个运输层协议传送数据。

   分用指接收方的运输层在剥去报文的首部后能够把这些数据正确交付到目的应用进程。

   差错检测:添加伪首部,计算检验和。计算检验和时,要在UDP用户数据报之前增加12个字节的伪首部。这个伪首部只是在计算检验和时,临时添加在UDP用户数据报前面,得到一个临时的UDP用户数据报。伪首部既不向下传送也不向上递交。UDP的检验和是把首部和数据部分一起检验

3、特点:

  1)无连接:意思就是在通讯之前不需要建立连接,直接传输数据。

  2)UDP使用尽最大努力交付;不保证可靠交付。

  3)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。也就是说,UDP一次交付一个完整的报文。

  4)UDP没有拥塞处理控制,因此网络出现的拥塞不会使源主机的发送速率降低。

  5)UDP支持一对一、一对多、多对一和多对多的交互通信。 UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短。

       

       

四、TCP协议

1、TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

2、特点:

  1)TCP是面向连接的运输层协议。应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。

  2)一条TCP连接只能有两个端点(endpoint),每一条TCP连接只能是点对点的(一对一)。

  3)TCP提供可靠交付的服务,也就是无差错、不丢失、不重复、按序到达。

  4)TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。 面向字节流。虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流

  5)TCP对应用进程一次把多长的报文发送到TCP的缓存中是不关心的。TCP根据堆放给出的窗口值和当前网络拥塞的程度来决定一个报文段应包含多少个字节(UDP发送的报文长度是应用程序给出的)。

3、TCP的连接

  TCP连接的端点叫做套接字(socket)插口端口号拼接到(contatenated with) IP地址即构成了套接字,如IP地址是192.3.4.5而端口号是80,那么套接字就是192.3.4.5:80。就是 套接字socket=(IP地址:端口号)

  每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定。即:
  TCP连接::={socket1, socket2}={(IP1:port1),(IP2:port2)}

4、报文头

       

URG: 标识紧急指针是否有效
ACK: 标识确认序号是否有效
PSH: 用来提示接收端应用程序立刻将数据从tcp缓冲区读走
RST: 要求重新建立连接. 我们把含有RST标识的报文称为复位报文段
SYN: 请求建立连接. 我们把含有SYN标识的报文称为同步报文段
FIN: 通知对端, 本端即将关闭. 我们把含有FIN标识的报文称为结束报文段

五、可靠传输的工作原理

1、采用停止等待协议:每次发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。

  出现差错:

  (1)接收M1时检测出了差错就丢弃M1,其他什么也不做(不通知A收到有差错的分组),也可能是M1在传输过程中丢失了,这时B当然什么都不知道,这两种情况下,B都不会发送任何信息。A只要超过了一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组,这就叫做超时重传。所以就要在每发送完一个分组设置一个超时计时器

  

(2)自动重传请求ARQ: B所发送的对M2的确认丢失了。A在设定的超时重传时间内没有收到确认,但并无法知道是自己发送的分组出错、丢失,或者是B发送的确认丢失了。因此A在超时计时器到期后就要重传M2。现在应注意B的动作,假定B又收到了重传的分组M2。此时应采取两个行动:(1) 丢弃这个重复的分组M2,不向上层交付;(2) 向A发送确认。

    

2、采用流水线传输:停止等待协议的优点是简单,但缺点是信道利用率太低。

  流水线传输就是发送方可连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。这样可使信道上一直有数据不间断地在传送。显然这种传输方式可获得很高的信道利用率。当使用流水线传输时,就要使用下面介绍的连续ARQ协议滑动窗口协议
  (1)连续ARQ协议: 发送方每收到一个确认,就把发送窗口向前移动一个分组的位置。

    

  接收方一般都是采用累积确认的方式,也就是接收方不必对收到的分组逐个发送确认,而是可以在收到几个分组后,对按序到达的最后一个分组发送确认,表示这个分组为止的所有分组都已正确收到了。累积确认的优点是容易实现,即使确认丢失也不必重传。但缺点是不能向发送方反映出接收方已经正确收到的所有分组的信息。

六、TCP可靠传输的实现     

  TCP的滑动窗口是以字节为单位的。假定A收到了B发来的确认报文段,其中窗口是20(字节),而确认号是31(表明B期望收到的下一个序号是31,而序号30为止的数据已经收到了),据此两个数据,A就构造出自己的发送窗口(长度为20,序号为31~50)。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。 

 发送方和接收方都有缓存,发送缓存用来暂时存放: (1)发送应用程序传送给发送方TCP准备发送的数据;

 (2)TCP已发送但尚未收到确认的数据。接收缓存用于暂时存放:

    1)按序到达的、但尚未被接收应用程序读取的数据;

    2)未按序到达的数据。

                                                 

   当出现错误时,因为在31没有到达前,32,33提前到达,此时B仍然向A发送的确认报文段中的报文号是31(期待收到的)。

   选择确认SACK工作原理,因为32,33都在接受窗口之内,B会先收下这些数据,然后把这些信息准确告诉A,使A不要再重复发送这些已经收到的数据;

   要使用选择确认SACK,必须双方先商量好,在TCP报文段中增进选择确认SACK选项,由于SACK文档没有指明发送方应当怎样相应SACK,因此大多数实现

   还是重传所有未被确认的数据块。

                                         

  当B收到31~33时,把这三个数据交付给主机,然后删除这三个数据,接收窗口向前滑动3个,并向A发送确认,期待号是34。A收到确认号后,发送窗口向前移动3个。

七、TCP的流量控制

  (1)利用滑动窗口来实现流量控制:实现如图

     (2)流量控制:让发送方的发送速率不要太快,要让接受方来得及接收。

   

   设A向B发送数据,建立连接时,B告诉A:“我的接受窗口rwnd = 400”,因此,发送方A的发送窗口不能超过接受方B的接受窗口数值。

   从上图可以知道,B进行了三次流量控制,rwnd = 300 , rwnd = 100, rwnd = 0

八、TCP的拥塞控制

1、拥塞:对资源的需求总和 > 可用资源

   例如:一个路由器没有足够的缓存空间,它会丢弃新到达的分组。分组被丢弃,发送方又会重传这一分组,甚至多次重传,加剧拥塞。

2、拥塞控制:防止过多的数据注入到网络中,这样可以是网络中的路由器或链路不致过载。

3、进行拥塞控制的算法:

  (1)慢开始算法:由小到大逐渐增大发送窗口。(发送方让自己的发送窗口等于拥塞窗口)

      cwnd = 1 ,初始拥塞窗口为1,只能发送一个报文段。设置慢开始门限ssthresh

  (2)当拥塞窗口大小达到门限时,使用拥塞避免算法;

      拥塞避免:每隔一个往返时间RTT,就让cwnd + 1

  (3)当出现超时时,判断为网络拥塞;设置拥塞窗口为1,调整门限为 cwnd / 2,重新慢开始、拥塞避免算法;

  (4)当发送方连续接收到3个对同一个报文段的重复确认时,发生了个别报文段的丢失,采用快恢复算法,调整门限为 cwnd / 2,并开始执行拥塞避免算法

              

九、TCP的三次握手,四次挥手

1、TCP建立连接的过程叫做握手,在通信之前,会先通过三次握手的机制来确认两端口之间的连接是否可用。而UDP不需要确认是否可用,直接传。

                      

解释:(1)序号 : seq                (3)确认:ACK

   (2)确认序号:ack    (4)同步 :SYN,SYN=1表示建立连接

第一次握手:SYN=1,seq=x

      客户端想与服务器进行连接了,所以状态变为主动打开,SYN = 1,TCP规定,SYN报文段不能携带数据,但消耗一个序号,随机选择一个初始序号seq=x。

      此时没有相应动作,与ACK无关。

      发送完请求连接报文后,客户端的状态就变为了SYN_SENT,可以说这个状态是等待发送确认(为了发送第三次握手时的确认包)。

第二次握手:服务端接收到连接请求报文后,从LSTTEN状态变为被动打开状态,然后给客户端返回一个报文。

      SYN = 1, ACK = 1,seq = y, ack = x +1

      服务器端建立连接后做出确认响应:SYN = 1, ACK = 1

      SYN报文段不能携带数据,但消耗一个序号,随机选择一个初始序号seq=y。

      因为到序号为x为止的所有数据都收到了,所有告诉客户端,期待序号为x+1 ,即 ack = x + 1

      发完后,变为SYN_RCVD状态(也可以说是等待接受确认状态,接受客户端发过来的确认包)

第三次握手:客户端收到服务器端的确认和知道服务器端也已经准备好了连接后,还会发一个确认报文到服务器端,

      告诉服务器端,我接到了你发送的报文,同时发送向服务器端的数据

      ACK = 1 ,seq = x + 1, ack = y+1

      因为到序号为y为止的所有数据都收到了,所有告诉服务器端,期待序号为y+1 ,即 ack = y + 1

此时,服务器端收到确认后,TCP连接进入已连接状态,可以发送http请求了。 

总结:起初A和B都处于CLOSED状态——B创建TCB,处于LISTEN状态,等待A请求——A创建TCB,发送连接请求(SYN=1,seq=x),进入SYN-SENT状态——B收到连接请求,向A发送确认(SYN=ACK=1,确认号ack=x+1,初始序号seq=y),进入SYN-RCVD状态——A收到B的确认后,给B发出确认(ACK=1,ack=y+1,seq=x+1),A进入ESTABLISHED状态——B收到A的确认后,进入ESTABLISHED状态。

2、四次挥手

  

FIN:报文的终止控制位,FIN = 1表示要释放连接,FIN报文段即使不携带数据,也要消耗一个序号

第一次挥手:Client端发起中断连接请求,也就是发送FIN报文。并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1(终止等待1)状态,等待B的确认。

      FIN = 1 ,seq = u, u 等于前面已传过的数据的最后一个字节的序号加1

第二次挥手:Server端接到FIN报文后发出确认ACK = 1,发出确认号ack = u+1, 告诉Client端此时的我的序号为v,

      seq = v , v 是服务器端前面已传送过的数据的最后一个字节的序号加1,

      服务器端进入CLOSE-WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务器的连接释放。

A收到B的确认后,进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。

第三次挥手:若服务器端没有要向客户端发出的数据,B发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),B进入LAST-ACK(最后确认)状态,等待A的确认。seq = w  : 服务器端可能又发了一些数据

第四次挥手:客户端收到服务器端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),

      客户端进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。

总结:起初A和B处于ESTABLISHED状态——A发出连接释放报文段并处于FIN-WAIT-1状态——B发出确认报文段且进入CLOSE-WAIT状态——A收到确认后,进入FIN-WAIT-2状态,等待B的连接释放报文段——B没有要向A发出的数据,B发出连接释放报文段且进入LAST-ACK状态——A发出确认报文段且进入TIME-WAIT状态——B收到确认报文段后进入CLOSED状态——A经过等待计时器时间2MSL后,进入CLOSED状态

注意点:

1)为什么A还要发送一次确认呢?可以二次握手吗?

  答:主要为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。如A发出连接请求,但因连接请求报文丢失而未收到确认,于是A再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,A工发出了两个连接请求报文段,其中第一个丢失,第二个到达了B,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达B,此时B误认为A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接,不采用三次握手,只要B发出确认,就建立新的连接了,此时A不理睬B的确认且不发送数据,则B一致等待A发送数据,浪费资源。

2)为什么连接的时候是三次握手,关闭的时候却是四次握手?

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

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

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。

 

借鉴博客:https://www.cnblogs.com/Andya/p/7272462.html

     https://www.2cto.com/kf/201709/680298.html

                  https://www.cnblogs.com/zhangyinhua/p/7610922.html

原文地址:https://www.cnblogs.com/dongtian-blogs/p/10783468.html