运输层简介

通过IP网络层的学习,我们知道IP协议能够把源主机A发送出来的分组按照首部中的目的地址,送交到目的主机B。那么,为什么还需要运输层呢?
从IP层来说,通信的两端是两台主机,即常说的点对点通信。但是在计算机网络中真正通信的实体是主机中运行的进程,是它们进行数据的交互。所以IP网络层只是把分组交付给了主机,而却没有交付给真正进行通信的进程,所以需要运输层来指出从网络中接收到的数据包该上交给那个进程。这就是常说的端对端通信
由于在同一时刻主机可能运行了多个网络运用,所以这时就需要运输层能够区分网络层的包应该交付给那个应用。这时就需要有个标志用于说明交于某个应用,在计算机网络中使用端口号进行标识。多个应用进程都可以使用运输层协议进行传送数据,即运输层拥有复用功能,同时在接收到的分组后,剥去报文的首部后能够把这些数据正确交付目的应用进程,所以运输层也要拥有分用功能。下图是两台主机中进程之间的信息交付流程。
在这里插入图片描述
TCP/IP中运输层用16位端口号来标志一个端口,端口号分为:系统端口号(0 - 1023)、登记端口号(1024 - 49151)、端户端使用的端口号(49152 - 65535)。下面使常用的熟知端口号:
在这里插入图片描述
其中运输层提供应用进程间的逻辑通信中的逻辑通信指的是:应用层只要把应用报文交给下面的运输层,运输层就可以把这些报文传送到对方的运输层,好像通信就是沿着水平方向直接传送数据。但事实上这两个运输层之间并没有一条水平方向的物理连接。
运输层向高层用户屏蔽了下面网络核心的细节,它使应用进程看见的就是好像在两个运输层实体之间有一条端到端的逻辑通信信道。运输层需要对收到的报文进行差错校验。当IP数据包到达目的主机后,向上层交付时,要是发现端口号不对(即没有此端口的进程),便会向发送方发送“端口不可到达”的差错控制报文。
运输层的两个主要协议:用户数据报协议UDP和传输控制协议

UDP协议

UDP主要特点

  • UDP是无连接的,即发送数据之前不需要建立连接
  • UDP使用尽最大努力交付,即不保证可靠交付
  • UDP是面向报文的,即发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层(对报文即不合并也不拆分)
  • UDP没有拥塞控制,即网络出现了拥塞不会使源主机的发送速率降低
  • UDP支持一对一、一对多、多对一和多对多的交互通信
  • UDP的首部开销小,只有8个字节
    UDP最大的优点就是其实时性高以及简单,UDP的首部格式如下图:
    在这里插入图片描述
  • 伪首部并不是UDP用户数据报真正的首部,只是用在计算校验,并不向上递交也不向下传送。
  • 端口号用于标志通信的进程
  • 长度:整个用户数据报的长度
  • 校验和:校验整个用户数据报

TCP协议

TCP主要特点

  • TCP是面向连接的运输层协议,即应用程序在使用TCP协议之前,必须先建立TCP连接,传完数据后,必须释放已经建立的TCP连接。
  • 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点
  • TCP提供可靠交付的服务
  • TCP面向字节流,TCP通信中是根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文应包含多少个字节。
    每一条TCP连接有两个端点,那么TCP连接的端点是什么呢?TCP连接的端点叫做套接字或插口。套接字由端口号拼接到IP地址。在Linux中无论是TCP协议还是UDP协议都是使用套接字进行通信的。

TCP报文段的首部格式

在这里插入图片描述
TCP报文段首部的前20个字节是固定的,后面4N个字节是根据需要而增加的选项,下面简单介绍各个字段的含义。

  • 端口号:分别写入源端口和目的端口,用于标志上层应用的类型。
  • 序号:序号使用mod 232运算,首部中的序号字段值指的是本报文段所发送的数据的第一个字节的序号。TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号,整个要传送的字节流的起始序号必须在连接建立时设置。
  • 确认号:期望收到对方下一个报文段的第一个数据字节的序号
  • 数据偏移:指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。即TCP报文的首部长度
  • 紧急URG:URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送。发送方把紧急数据插入到本报文数据的最前面,而在紧急数据后面的数据仍然是普通数据。这时要与首部中紧急指针字段配合使用。
  • 确认ACK:当ACK=1时确认号字段才有效,否则确认号无效。TCP规定在连接建立后所有传送的报文段都必须把ACK置1.
  • 推送PUH:TCP使用推送push操作,这时发送方把PSH置1,并立即创建一个报文段发送出去;同样接收方在接收到PSH=1的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。
  • 复位RST:RST =1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立运输连接。此字段还用于拒绝一个非法的报文段或拒绝打开一个连接。
  • 同步SYN:在连接建立时用来同步序号。SYN = 1,ACK = 0时,表明这是一个连接请求报文段。若同意建立连接则响应的报文段中SYN = 1,ACK = 1。
  • 终止FIN:用来释放一个连接,当FIN=1时,表明此报文段的发送方数据已发送完毕,并要求释放运输连接。
  • 窗口:窗口指的是发送本报文段的一方的接收窗口。窗口值告诉对方,从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量(字节为单位)。
  • 校验和:检验和校验的范围是整个TCP报文(即包括首部 和数据这两部分)。与UDP类似也需要添加12个字节的伪首部
  • 紧急指针:仅在URG=1时此字段才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。注意,即使窗口为零时也可以发送紧急数据
  • 选项:长度可变,最长可达40字节。有最大报文段长度MSS,窗口扩大、时间戳、选择确认等选项。

TCP的运输连接管理

TCP是面向连接的协议,运输连接是用来传送TCP报文的。TCP运输过程和电路交互一样存在着三个阶段,即连接建立、数据传送、连接释放。其中所说的面向连接指的是TCP通信时,每一条TCP信道只能连接两个端口,在通信过程中这两个端口(包括对应的资源:传输控制块TCB)一直分配给正在通信的进程使用,其它应用无法使用 。这里纠正下,之前对面向连接的理解还是存在些误解的。面向连接指的是TCP在传输数据之前需要建立连接,确定双方的序号以及窗口之类的。在后续的传输中需要靠这些值来判断传输是否成功。之前说的传输控制块TCB不是重点,每建立一个连接内核都会分配一些资源给应用,像服务器中存在的一对多通信,其socket资源是公共的。现在的理解是这样,要是读者有更好的理解欢迎指正。

建立连接

TCP建立连接使用的是三次握手,在建立连接过程中需要解决以下问题:

  • 要使每一方能够确知对方的存在
  • 要允许双方协商一些参数(如序列号、最大窗口值、是否使用选项等等)
  • 能够对运输实体资源进行分配(缓存大小)
    握手过程如下:建立连接使用SYN字段,TCP规定SYN报文段不能携带数据,但要消耗一个序号,ACK报文段可以携带数据,但如果不携带数据则不消耗序号。注意其中第二次握手也可以拆成两个报文段,先发送一个确认报文(即ACK = 1,ack = x+1)然后再发送一个同步报文段(SYN = 1,seq = y)这样的过程就变成了四报文握手,效果是一样的。其中上述的ACK就是首部字段ACK,而ack则为确认号。
    在这里插入图片描述
    B给A返回数据后就能说明AB都存在,这里为什么A最后还要发送一次确认呢?这里主要是为了防止已失效的连接请求报文突然又传送到了B,因而产生错误。如:A发出的第一个连接请求报文由于在某网络结点长时间滞留,而A没有收到确认报文继续发送一次连接请求,正常通信…释放连接。在释放连接后在网络中滞留已久的那个请求报传送给了B,这是B误认为是A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接。假如不采用第三次报文握手,那么B发出确认后,新的连接就建立了。这时B认为新的运输连接已经建立了,并一直等待A发来数据,B的许多资源就这样白白浪费了。利用这点特性,能对服务器造成攻击,很多主机都向服务器只发送一次SYN请求,然后就关闭进程,服务器会一直等待着A的回应,而浪费资源每个sock中的listen都有一个队列长度,超过了就会丢弃。所以正常的请求会无法建立。这就是常说的SYN攻击

TCP的连接释放

发送释放连接报文段首部的终止控制位FIN要置1,同样TCP规定,FIN报文段即使不携带数据也要消耗一个序号
在这里插入图片描述
流程是:

  • A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。发送报文(FIN置1,seq = u,u为前面已传过的数据的最后一个字节的序号加1),进入FIN-WAIT-1状态,等待B的确认。
  • B收到连接释放报文后,即发出确认(ACK = 1,seq = u,ack = u+1),进入CLOSE-WAIT状态。TCP服务器进程这时应该通知高层应用进程,得知从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭状态。
  • A收到B的确认后,就进入FIN-WAIT-2状态,等待B发出的连接释放报文。
  • 若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出释放报文,这时B就进入LAST-ACK状态,等待A的确认。
  • A在收到B连接释放报文段后,必须对此发出确认,发送报文,然后进入TIME-WAIT状态。请注意TCP连接还没有释放掉,必须经过时间等待计时器设置的时间2MSL后,A才进入到CLOSE状态。每次发出ACK确认后都会重置等待计时器。
  • B收到A的确认后立刻进去CLOSE状态。
    为什么A在TIME-WAIT状态必须等待2MSL的时间?
    为保证A发送的最后一个ACK报文能够到达B,这个ACK可能会被丢失,B在相应的时间内没有收到ACK报文确认会重传这个FIN报文,B需要在这个等待时间内重传一次确认。否则B无法进入CLOSE状态。再者可以防止三次握手中提到的已失效的连接请求报文段出现在本连接中,因为经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。
    释放连接后AB都会撤销相应的传输控制块TCB。上述中的最长报文段寿命MSL基本上设置为2分钟。在TCP协议中除了时间等待计时器外,还设有一个保活计时器,用于防止通信过程中设备出现了故障不能正常通信,从而导致接收端白白的一直等待浪费资源。保活计时器通常是设置为2小时,若2小时内没有收到数据报,就会发送探测报文段,每隔75秒发送一次,若连续发送10个探测报文段后仍无响应,则直接关闭这个连接。

TCP可靠传输的工作原理

我们知道TCP发送的报文段是交给IP层传送的,但是IP层只能提供尽最大努力服务,因此TCP必须采用适当的措施才能使得两个运输层之间的通信变得可靠。这里使用的是确认和重传机制,也常称自动重传请求ARQ

  • 停止等待协议
    停止等待协议就是每发送完一个分组就停止发送,等待对方的确认,在收到确认后再发送下一个分组。发送方在发送一个分组后设置一个超时计时器,在计时器超时后,重新发送上一次发送的分组。而在计时器到期之前收到了对方的确认就撤销已设置的超时计时器。像这种可靠传输协议常称为自动重传请求ARQ
    在这里插入图片描述
    停止等待协议的优点是简单,但缺点是信道利用率太低。为了提高传输效率,发送方可以不使用低效率的停止等待协议,而是采用流水线传输。即发送方可以连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。如下图所示:
    在这里插入图片描述
    这就是连续ARQ协议,发送方维持发送窗口,在接收到分组确认后于是把发送窗口向前移动一个分组的位置。接收方一般都是采用累积确认的方式,在收到多个分组后,对按序到达的最后一个分组发送确认

在TCP协议中,保证数据能够稳定运行的机制特别多,其中最主要的就是滑动窗口控制。类似于上述的流水线传输,在条件允许的情况下,会持续地发送数据包。接收方会把接收方缓存的情况(端口大小)告诉发送方,发送方根据窗口给接收方发送数据。
在网络通信中,应用层把需要发送的数据下交给运输层后,就去处理别的事情了,由于TCP是面向字节流传输,那么TCP缓存中收到了应用层的数据后什么时候发送呢?
TCP发送时机有三种:TCP维持一个变量,它等于最大报文段长度,缓存中存放的数据达到MSS字节时,发送;PUCH推送,用于需要紧急处理的数据,TCP接收到应用层的PUSH指令后,立刻发送报文段;TCP启动计时器,计时器的时间到了就发送。
TCP通信中流量控制就是让发送方发送速率不要太快,要让接收方来得及接收。其实就是控制窗口的大小。然后为了让TCP效率更高,往往采用Nagle算法,先把接收到缓存中的数据发送出去,接收到确认后,再把缓存中的所有数据都发送出去,继续等待接收确认…;同时还规定了,如缓存数据已达到发送窗口大小的一半或已达到报文段的最大长度时,就立即发送一个报文段。接收方也是一样,接收方已有足够空间容纳一个最长的报文段,或者等到接收缓存已有一半空闲空间。接收方才会发出确认报文。
在流量控制中,有一个零窗口持续计时器,只要TCP接收的一方收到对方的零窗口通知,就启动持续定时器,时间到期。就发送一个零窗口探测报文段,这样就可以打破死锁的僵局(发送方一直等待非零窗口的报文,但是此报文却丢失了)。、
TCP的拥塞控制机制和流量控制实现时类似的,当网络中通信量太大时,就会通过窗口控制发送数据的速率,从而减少拥塞程度。但是拥塞和流量控制不是一个概念。

发布了35 篇原创文章 · 获赞 1 · 访问量 1870

猜你喜欢

转载自blog.csdn.net/lzj_linux188/article/details/104500164