传输层TCP与UDP

TCP概念

TCP提供了一种面向连接、安全可靠,基于字节流的传输层控制协议。TCP是一种全双工传输方式,由于在保证数据可靠传输时使用了握手认证,超时重传,拥塞控制等操作,导致TCP传输效率相对较低,但是却保证了数据的准确性。

首部

  • 字段解析
  1. 源端口和目的端口:端口为我们提供了一种服务进程,用于标识不同的应用程序。假设我们将同一地址用于Web程序、FTP程序通信,使用端口可以用于识别出这些不同的服务程序,端口号各占2个字节;
  2. 序号:表示数据的第一个字节的序列号,由于TCP的数据交互是基于序列号的(控制滑动窗口),发送方通过序列号控制发送数据以及超时重传,接收方通过序列号控制乱序重排,占4个字节;
  3. 确认号:表示期望下次收到的序列号。比如服务器收到客户端发来的报文段,其序列号字段值为501,并通过计算可知数据长度为200,所以服务器可以算出最后一个字节的序列号为700。这表明服务器正确收到了客户端发送的序列号到700为止的数据,因此,服务器期望下次收到的序列号为701,并将其作为确认号放入应答报文段中,占4个字节;
  4. 数据偏移:表示TCP报文段的第一个数据距离报文段起始处有多远。由于TCP报文段首部长度不确定,20到60字节不等,所以需要一个字段用于找到数据起始处(占4位,单位是位,不是字节);数据偏移代表的是4字节的倍数,由于4位二进制最大可以表示15,所以数据偏移最大为4 * 15 = 60,这也是TCP报文段首部的最大长度;
  5. 保留:保留字段,暂时不使用;
  6. 紧急URG:表示报文段中的数据是紧急数据,需要马上处理。接收方收到这种类型的报文段后,不会像正常流程那样将数据追加到接收缓冲区末尾,而是插到缓冲区开始的位置,使得接收方立即读取当前数据;
  7. 确认ACK:只有当ACK位被置1时确认号才有用。TCP规定,连接建立后发送的所有报文段ACK位都必须置1,还没建立连接之前,ACK位的值为0;
  8. 推送PSH:当发送方希望数据可以立即发送给对端时,TCP会将报文段首部的PSH位置1,接收方同样将PSH位置1的报文段中的数据尽快告知应用程序(该控制位很少使用,因为TCP会自己决定什么时候应该使用PUSH操作);
  9. 复位RST:用于复位,表示连接出现错误,应当立即关闭。当TCP接收到复位报文段后会通知应用程序连接被复位,随后关闭连接
  10. 同步SYN:连接建立的过程中用于同步序列号,告知对方自己的起始序列号。可以根据对方的序列号初始化缓冲区起点(滑动窗口);
  11. 终止FIN:用于释放连接,若报文段中FIN控制位为1,表示已经将数据发送完毕,等待关闭连接;
  12. 窗口:表示发送该报文段的一方能够接收的字节数,用于控制接收方发送数据的个数(控制对端滑动窗口),双方可进行互相控制,占2个字节;
  13. 检验和:占2个字节,用于检验报文段是否出错。发送方根据发送的报文段计算检验和填入报文段首部,接收方根据规定的算法对接收的报文段重新计算,如果不匹配,表明报文段出错;
  14. 紧急指针:表示紧急数据的个数,因为报文段中可以既包含紧急数据也可以包含普通数据,该字段用于区分二者,占2个字节;
  15. 选项:长度可变, 最长为40字节,当没有使用选项字段时,TCP报文段首部共20字节。TCP选项比较常用的是MSS,即传输数据报文最大长度,与MTU相关联;

三次握手

TCP传输数据前建立连接与传输数据后关闭连接都需要双方进行握手进行,有时候关闭连接的握手我们也称为四次分手!通常情况下,都是从客户端发起连接的!

  • 总过程如下:

 

  • 三次握手过程

刚开始客户端处于close状态,服务端处于listen状态,接下来双方进行握手:

第一次握手:客户端发送一个请求数据包,数据包中包含SYN=1的同步序号,发送序列号Seq为随机值x(ISN),此数据包只包含首部,没有数据,首部选项中可能还存放着发送方的滑动窗口大小,用于控制网络拥塞(此过程第二次握手也可能同样存在)。发送完请求包后客户端状态为SYN_SEND,等待服务端确认;

第二次握手:服务端收到确认了客户端请求后,发送一个响应数据包(即SYN+ACK报文段),数据包中包含SYN=1的同步序号,确认序列号为x+1,告知客户端请求序列号x已经收到确认,同时服务端自己也发送一个请求序列号Seq为Y(ISN)随机值。由于还没建立连接,所以响应数据包同样只包含首部,不带有数据!发送完响应包后服务端状态为SYN_RECV,等待客户端确认;

第三次握手:客户端确认服务端的响应数据包后,回应一个数据包,数据包中包含确认服务端请求序列号ACK为Y+1和一个Seq为Y的序列号,向服务器发送ACK报文段后,这个报文段被服务端收到确认后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手,接下来双方就可以进行通信了!

 

  • 四次挥手

刚开始时,双方都处于ESTABLISHED状态,当其中一方传输完数据时,准备关闭自己的连接。这里假设发送方发起关闭请求通知:

第一次挥手:客户端发送完数据后,准备关闭连接,请求的数据包(ACK+FIN)中,包含了FIN=1,发送序列号为ISN的报文段,此时客户端为FIN_WAIT_1状态;

第二次挥手:服务端收到并确认客户端请求报文后,发送响应数据包,数据包中有确认序列号ACK为ISN+1,发送序列号为ISN,此时服务端为FIN_WAIT_2,同意客户端的连接关闭请求;

第三次挥手:服务端发送一个请求数据包(ACK+FIN),数据包包含了FIN=1和请求序列号值为ISN,此时服务器状态为LAST_ACK;

第四次挥手:客户端收到 FIN数据包之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值ISN + 1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过2MSL的等待时间段,以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态;服务端收到并确认报文后,连接关闭;

面试相关

1、(ISN)是固定的吗

三次握手的一个重要功能是客户端和服务端交换ISN(Initial Sequence Number), 以便让对方知道接下来接收数据的时候如何按序列号组装数据。如果ISN是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的。

2、什么是半连接队列

服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。

3.1、三次握手的第一次可以携带数据吗?为何?

不可以,三次握手还没有完成。

3.2、对方难道不可以将数据缓存下来,等握手成功再提交给应用程序?

这样会放大SYN FLOOD攻击。如果攻击者伪造了成千上万的握手报文,携带了1K+ 字节的数据,而接收方会开辟大量的缓存来容纳这些巨大数据,内存会很容易耗尽,从而拒绝服务。

4、第三次可以携带数据吗?为何?

可以。能够发出第三次握手报文的主机,肯定接收到第二次(服务器)握手报文,对吗?

因为伪造IP的主机是不会接收到第二次报文的。所以,能够发出第三次握手报文的,应该是合法的用户。尽管服务器侧的状态还没有“established”,接收到第三次握手的瞬间,状态就会切换为“established”,里面携带的数据按照正常流程走就好。

5、关闭连接的最后一个 ACK 丢失怎么办

实际上,在第三步中,客户端收到 FIN 包时,它会设置一个计时器,等待相当长的一段时间。如果客户端返回的 ACK 丢失,那么服务端还会重发 FIN 并重置计时器。假设在计时器失效前服务器重发的 FIN 包没有到达客户端,客户端就会进入 CLOSE 状态,从而导致服务端永远无法收到 ACK 确认,也就无法关闭连接。

6、为什么需要三次握手?

因为在网络请求中,我们应该时刻记住:“网络是不可靠的,数据包是可能丢失的”。假设没有第三次确认,客户端向服务端发送了 SYN,请求建立连接。由于延迟,服务端没有及时收到这个包。于是客户端重新发送一个 SYN 包。假设服务端接收到了第二个 SYN 包,建立了通信,一段时间后通信结束,连接被关闭。这时候最初被发送的 SYN 包刚刚抵达服务端,服务端又会发送一次 ACK 确认。由于两次握手就建立了连接,此时的服务端就会建立一个新的连接,然而客户端觉得自己并没有请求建立连接,所以就不会向服务端发送数据。从而导致服务端建立了一个空的连接,白白浪费资源。

 

流量控制

如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。

利用滑动窗口机制可以很方便地在TCP连接上实现对发送方的流量控制。

设A向B发送数据。在连接建立时,B告诉了A:“我的接收窗口是 rwnd = 400 ”(这里的 rwnd 表示 receiver window) 。因此,发送方的发送窗口不能超过接收方给出的接收窗口的数值。请注意,TCP的窗口单位是字节,不是报文段。假设每一个报文段为100字节长,而数据报文段序号的初始值设为1。大写ACK表示首部中的确认位ACK,小写ack表示确认字段的值ack。

从图中可以看出,B进行了三次流量控制。第一次把窗口减少到 rwnd = 300 ,第二次又减到了 rwnd = 100 ,最后减到 rwnd = 0 ,即不允许发送方再发送数据了。这种使发送方暂停发送的状态将持续到主机B重新发出一个新的窗口值为止。B向A发送的三个报文段都设置了 ACK = 1 ,只有在ACK=1时确认号字段才有意义。

TCP为每一个连接设有一个持续计时器(persistence timer)。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口控测报文段(携1字节的数据),那么收到这个报文段的一方就重新设置持续计时器,看是否能继续发送数据。

拥塞控制

发送方维持一个拥塞窗口 cwnd ( congestion window )的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口。

发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。

1.慢开始和拥塞避免

通常在刚刚开始发送报文段时,先把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口指数级增加至多一个MSS的数值。

为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量为MSS最大值的一半。慢开始门限ssthresh的用法如下:

  • 当 cwnd < ssthresh 时,使用上述的慢开始算法。
  • 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
  • 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法。

2.快重传和快恢复

快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时才进行捎带确认。详细看文章关于 TCP/IP,必知必会的十个问题

 

UDP概念

UDP 协议是面向无连接的协议,它只会把数据传递给接收端,但是不会关注接收端是否真的收到了数据。但是这种特性反而适合多播,实时的视频和音频传输。因为个别数据包的丢失并不会影响视频和音频的整体效果,最大的特点就是简单。

首部

包长度表示 UDP 首部的长度和 UDP 数据长度之和。

校验和用来判断数据在传输过程中是否损坏。计算这个校验和的时候,不仅考虑源端口号和目标端口号,还要考虑 IP 首部中的源 IP 地址,目标 IP 地址和协议号(这些又称为 UDP 伪首部)。这是因为以上五个要素用于识别通信时缺一不可,如果校验和只考虑端口号,那么另外三个要素收到破坏时,应用就无法得知。这有可能导致不该收到包的应用收到了包,该收到包的应用反而没有收到。当然这个原理也同样适合TCP协议。

TCP/UDP两者区别

面向报文

面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会是IP太小。

面向字节流

面向字节流的话,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。

什么时候应该使用TCP?

当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。 

什么时候应该使用UDP?

当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP

 

数据分片

  • 数据包太长时,需分包处理,那么接收时如何判断和处理呢?

1、在客户端将你要发送的内容进行分块,每块内容进行编号,然后发送;

2、服务端在接收到你的分块数据以后,根据你的客户端数据内容的编号重新组装;

3、一般我们在发送数据的时候,尽量采用比较小的数据块的方式(我的都没有超过1024的),数据块太大的话容易出现发送和接收的数据时间长,匹配出问题。

  • TCP分片

TCP协议自己会进行分段,TCP报文段的每个分段中都有TCP首部,到了端点后根据TCP首部的信息在传输层进行重组。

  • UDP分片

UDP不会分段,就由IP来分。IP数据报分片后,只有第一片带有UDP首部或ICMP首部,其余的分片只有IP头部,到了端点后根据IP头部中的信息再网络层进行重组。但是对于UDP分包,只要组装完的数据校验失败,照样也是会被丢弃,但UDP没有丢包重传机制,除非自己提供重传和乱序处理!

  • MTU与MSS

TCP分段的原因是MSS,IP分片的原因是MTU,由于一直有MSS(MTU-TCP首部-IP首部)<=MTU,很明显,分段后的每一段TCP报文段再加上IP首部后的长度不可能超过MTU,因此也就不需要在网络层进行IP分片了。因此TCP报文段很少会发生IP分片的情况。

  1. MTU是最大传输单元,是用于数据链路层控制一次传输可最达到最大长度的数据帧;
  2. MSS是最大分段大小,是TCP协议中使用的,MSS是TCP数据包每次能够传输的最大数据分段,TCP报文段的长度大于MSS时,要进行分段传输。

重传机制

  • 超时重传

若在传输过程中有数据包未收到,则对方会选择死等机制:

  1. 等到timeOut时,仅重传timeout的包,节省带宽,时间长;
  2. 等到timeOut时,重传未收到到后面所有数据包,时间短,浪费带宽;
  • 快速重传

如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。快速重传的好处是不用等timeout了再重传,但是带来的问题也是重传部分丢失数据包还是丢失数据包后面的所有呢,这是个问题。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值