TCP协议如何实现可靠传输

流量控制和拥塞控制区别:

流量控制:是某个TCP接收方针对其缓存情况通告TCP发送方窗口大小所采取的措施,而拥塞控制TCP发送方针对网络拥塞情况所采取的措施。

流量控制:用于防止发送方发送过快而使接受方无法接受拥塞控制用于抑制发送方的发送速率以防止其占用过多的网络资源

对比滑动窗口和拥塞窗口

滑动窗口是控制接收以及同步数据范围的,通知发送端目前接收的数据范围,用于流量控制,接收端使用。拥塞窗口是控制发送速率的,避免发的过多,发送端使用。因为tcp是全双工,所以两边都有滑动窗口。
两个窗口的维护是独立的,滑动窗口主要由接收方反馈缓存情况来维护,拥塞窗口主要由发送方的拥塞控制算法检测出的网络拥塞程度来决定的。

拥塞窗口控制sender向connection传输数据的速率,使这个速率为网络拥堵状况的函数。

 

流量控制的方法:TCP为提供可靠数据传输而使用的方法涉及序号确认超时重传滑动窗口等可靠数据传输机制。

几种拥塞控制方法:

慢启动、拥塞避免(加性增、乘性减)、快恢复、快重传。

快恢复:一旦收到3个冗余的ACK,就取消慢启动并转入拥塞避免阶段。(原来是无论发生哪种丢包事件都立即将拥塞窗口减速至1个MSS,然后转入慢启动阶段)

快速重传:一旦收到某报文段的3个冗余的ACK,就可以在该报文段定时器过期之前重传丢失的报文段。

滑动窗口:

https://blog.csdn.net/wdscq1234/article/details/52444277?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control

 

TCP 三次握手、四次挥手以及安全传输

https://www.it610.com/article/1295352226029576192.htm

3.TCP拥塞控制

作用:防止过多的数据诸如网络,使网络负载过大,让网络能够承载现在的负荷,实现供求平衡

控制方法:

接受窗口RWin -- 根据接收方自身读取速度以及接收缓存的大小来设定(在缓冲区存在)

拥塞窗口CWin -- 发送端根据自己估计的网络拥塞程度设置的窗口值(假想的实际上不存在)

设置原则:

网络没有拥塞,拥塞窗口设置大一些保证更多的数据在网络条件好的时候发出去,

网络出现拥塞,拥塞窗口就小一些,以便当前网络上注入的数据少一些,

从而保证传输。

发送窗口的上限值 = Min[ CWin,RWin ]

发送端发送多少数据以接收窗口和拥塞窗口中较小的为基准

当 RWin < CWin 时,是接收端的接收能力限制发送窗口的最大值。

当 RWin > CWin时,则是网络的拥塞情况限制发送窗口的最大值。

拥塞控制具体实现:

TCP 三次握手、四次挥手以及安全传输_第3张图片

 

1.慢启动:指数增长,对拥塞窗口进行增加,保证尽可能的传输数据,每次收到一个确认就将窗口增大,增加到阈值就进入拥塞避免。

2.拥塞避免:使用加法增大算法,每经过一个数据包的往返时间RTT才会将拥塞窗口+1而不是加倍,当增加到当前网络能够承受的最大值的时候就要进行乘法减小算法,将阈值变成当前最大窗口(网络能够负载的最大能力)的一半,然后再将拥塞窗口减到1,重新进行慢启动,拥塞避免的过程

3.快重传:收到三个重复确认,不用等到重传计时器到期就直接发送丢失的报文

4.快恢复:一旦发生丢失报文的情况,就悲观的认为当前网络已经到了负载能力最大的地步,就直接开始执行拥塞避免,而不用等到慢启动到达阈值之后再启动拥塞避免。(一旦收到3个冗余的ACK,就取消慢启动并转入拥塞避免阶段。(原来是无论发生哪种丢包事件都立即将拥塞窗口减速至1个MSS,然后转入慢启动阶段)

4.TCP流量控制

简述:就是给返回报文字段中添加一个流量窗口大小的字段,从而告知发送方,下一次发送数据的时候需要根据流量窗口的大小来发送数据,从而防止发送方发送过快而接收方根本读不过来。

实现流量控制的方法:

序号,确认,超时重传,滑动窗口等可靠性传输机制

滑动窗口:发送方的缓冲区一部分是窗口,那么窗口里放的数据是允许发送的数据和已发送但未确认的数据,一旦发送并确认,窗口就会向发送方方向挪动,以便发送下一个数据。

接收方的缓冲区同样有一部分是窗口,存放的是允许接收和已接收但未确认的数据,一旦接收并确认,接收窗口就会向发送方方向(相反于自身方向)滑动。

发送窗口满就停止:当接收方一直不确认,发送方一直发送允许发送的数据,发送窗口中就全部都是已发送但未确认的数据,发送窗口就会变满,此时就停止发送。

接收方接收能力弱:接收方来不及接收数据就会通知发送方缩小窗口。

乱序报文解决:当接收方接收到乱序的报文会先将它存在窗口中并启动超时重传,等待发送方发送缺少的数据,最后再进行重组。

丢失报文解决:发送过程中报文丢失,接收方无法确认,那发送方就会一直发送,直到发送方窗口变满就会重新把丢失的报文发一遍。

TCP 三次握手、四次挥手以及安全传输_第4张图片

 

上述情况产生的问题:

RWin=0是因为接收方缓冲区满了,就是读取比较慢,等接收方读取后,接收方缓冲区就空下来,

这时候接收方向发送方发送RWin=400,但是很不巧这个报文段丢了,发送方一直在等待接收方说它空下来的消息,但是接收方不知道自己之前发送的丢了,所以也一直在等待发送方发送数据?

尴尬。。。怎么办?

别担心,持续计时器!!!!

只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器来预防发生上述问题。

工作原理:若持续计时器设置的时间到期就发送一个窗口探测报文段携带一个字节的数据。

就是说接收方给发送方说:你等下再发,我这窗口满了,我要是窗口空下来我就给你说。

发送方就一直等着也不是办法,所以就主动给接收方打个电话问一下:你看现在行不行?

接收方要是窗口空下

来就给发送方发送确认报文段也就是当前的窗口值:

如果确认报文段中窗口字段值为0则发送方就再设置持续计时器,

不是0就继续进行正常的发送和接收

当然如果老是0,发送方就不自己打电话问了,就设置一个周期,周期性发送探测。

6.如何实现UDP可靠通信?

https://www.jianshu.com/p/6c73a4585eba

概述

UDP不属于连接协议,具有资源消耗少,处理速度快的优点,所以通常音频,视频和普通数据在传送时,使用UDP较多,因为即使丢失少量的包,也不会对接受结果产生较大的影响。

传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。

最简单的方式是在应用层模仿传输层TCP的可靠性传输。下面不考虑拥塞处理,可靠UDP的简单设计。

  • 1、添加seq/ack机制,确保数据发送到对端
  • 2、添加发送和接收缓冲区,主要是用户超时重传。
  • 3、添加超时重传机制。

详细说明:送端发送数据时,生成一个随机seq=x,然后每一片按照数据大小分配seq。数据到达接收端后接收端放入缓存,并发送一个ack=x的包,表示对方已经收到了数据。发送端收到了ack包后,删除缓冲区对应的数据。时间到后,定时任务检查是否需要重传数据。

目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT

开源程序

1、RUDP(Reliable User Datagram Protocol)

RUDP 提供一组数据服务质量增强机制,如拥塞控制的改进、重发机制及淡化服务器算法等,从而在包丢失和网络拥塞的情况下, RTP 客户机(实时位置)面前呈现的就是一个高质量的 RTP 流。在不干扰协议的实时特性的同时,可靠 UDP 的拥塞控制机制允许 TCP 方式下的流控制行为。

2、RTP(Real Time Protocol)

RTP为数据提供了具有实时特征的端对端传送服务,如在组播或单播网络服务下的交互式视频音频或模拟数据。

应用程序通常在 UDP 上运行 RTP 以便使用其多路结点和校验服务;这两种协议都提供了传输层协议的功能。但是 RTP 可以与其它适合的底层网络或传输协议一起使用。如果底层网络提供组播方式,那么 RTP 可以使用该组播表传输数据到多个目的地。

RTP 本身并没有提供按时发送机制或其它服务质量(QoS)保证,它依赖于底层服务去实现这一过程。 RTP 并不保证传送或防止无序传送,也不确定底层网络的可靠性。 RTP 实行有序传送, RTP 中的序列号允许接收方重组发送方的包序列,同时序列号也能用于决定适当的包位置,例如:在视频解码中,就不需要顺序解码。

3、UDT(UDP-based Data Transfer Protocol)

基于UDP的数据传输协议(UDP-basedData Transfer Protocol,简称UDT)是一种互联网数据传输协议。UDT的主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。

顾名思义,UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向连接的双向的应用层协议。它同时支持可靠的数据流传输和部分可靠的数据报传输。由于UDT完全在UDP上实现,它也可以应用在除了高速数据传输之外的其它应用领域,例如点到点技术(P2P),防火墙穿透,多媒体数据传输等等。

7.TCP长连接,短连接,保活,心跳包

TCP短连接:

客户端想服务器发起连接请求,服务器接收到请求,然后双方建立连接。

客户端向服务器发送消息,服务器回应客户端,然后读写一次就完成了,这时候双方任何一个都可以发起close操作。不过一般都是客户端先发起close操作,原因是一般服务器除特殊情况外不会回复完客户端之后立即关闭连接。短连接一般只会在客户端/服务器之间传递一次读写操作

优点:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段

TCP长连接:

客户端向服务器发起连接请求,服务器接收请求,双方建立连接。客户端与服务器完成一次读写之后,他们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。

TCP保活:

为服务器应用提供,服务器应用需要知道客户主机是否崩溃。如果客户端已经消失,服务器就保留了一个半开放的连接,保活功能就是试图在服务器端检测到这种半开放的连接

如果一个给定的连接在两个小时内没有任何动作,则服务器就向客户发送一个探测报文段,客户主机必须处于以下四个状态之一:

1.客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位。

2.客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测 ,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。

3.客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。

4.客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探查的响应。

长连接和短连接的产生在于客户端和服务器采取的关闭策略

心跳包:

每隔一段时间(TCP默认2小时)固定发一次包(内容一般是很小的包或者只包含包头)给客户端,从而告诉服务器客户端还活着。只要send或者recv一下,结果为零,则为掉线

TCP 三次握手、四次挥手以及安全传输_第6张图片

三、TCP的11种状态转换

 

CLOSED:起始点,不在连接状态。可以主动打开连接,或者等待对端的连接。

-->收到“被动打开”报文,进入LISTEN状态。

-->收到“主动打开”报文,进入SYN_SENT状态。

-->收到任何报文段,发送RST报文段。

-->收到其它任何报文段,发出差错报文。

LISTEN:被动打开,TCP正在等待对端的连接请求。

-->收到“发送数据”报文,发送SYN报文段,进入SYN_SENT状态。

-->收到任何SYN报文段,发送SYN+ACK报文段,进入SYN_RECEIVED状态。

-->收到任何其它报文段或者报文,发送差错报文。

SYN_SENT:主动打开,发送完一个连接请求后等待回复。

-->超时,进入CLOSED状态。

-->收到SYN报文段,发送SYN+ACK报文段,进入SYN_RECEIVED状态。

-->收到SYN+ACK报文段,发送ACK报文段,进入ESTABLISHED状态。

-->收到任何其它报文段或者报文,发送差错报文。

SYN_RECEIVED:被动打开,接受连接请求以后进行确认同时也向对端发送连接请求发送,等待对方的回复。

-->超时,发送RST报文段,进入CLOSED状态。

-->收到ACK报文段,进入ESTABLISHED状态。

-->收到"关闭"报文,发送FIN报文段,进入FIN_WAIT_1状态。

-->收到RST报文段,进入LISTEN状态。

-->收到任何其它报文段或者报文,发送差错报文。

ESTABLISHED:三次握手完毕,TCP连接建立完成,可以传输数据。

-->收到FIN报文段,进入CLOSED_WAIT状态。

-->收到“关闭”报文,发送FIN报文段,进入FIN_WAIT_1状态。

-->收到RST或SYN报文段,发出差错报文。

-->收到数据或ACK报文段,调用输入模块。

-->收到“发送”报文,调用输出模块。

FIN_WAIT_1:四次挥手开始,主动关闭,发送断开连接请求,等待对端确认。

-->收到FIN报文段,发送ACK报文段,进入CLOSING状态(同时关闭)。

-->收到FIN+ACK报文段,发送ACK报文段,进入FIN_WAIT状态(?)。

-->收到ACK报文段,进入FIN_WAIT_2状态。

-->收到任何其它报文段或者报文,发送差错报文。

FIN_WAIT_2:接收对方确认,但未接受对方的断开连接请求。

-->收到FIN报文段,发送ACK报文段,进入TIME_WAIT状态。

CLOSING:主动关闭的一方本希望收到对方的ACK却收到了对方的断开连接请求。

-->收到ACK报文段,进入TIME_WAIT状态。

-->收到任何其它报文段或者报文,发送差错报文。

TIME_WAIT:对方确认后发起断开连接请求,需要等待2MSL保证正常关闭。

-->超时,进入CLOSED状态。

-->收到任何其它报文段或者报文,发送差错报文。

CLOSE_WAIT:被动关闭,确认对端的连接终止请求,但是未向对端发送连接终止请求(可能数据没传完)。

-->收到"关闭"报文,发送FIN报文段,进入LAST_ACK状态。

-->收到任何其它报文段或者报文,发送差错报文。

LAST_ACK:数据传完,向对端发起断开连接请求后等待确认。

-->收到ACK报文段,进入CLOSED状态。

-->收到任何其它报文段或者报文,发送差错报文。

CLOSED:终点,不在连接状态。可以主动打开连接,或者等待对端的连接。

 

(1)TIME_WAIT状态(假设客户端主动,服务器端被动)

从状态图中我们可以发现,执行主动关闭的那端(最终重传ACK的那端)会经历这个状态。这个状态停留是的时间是2MSL(MSL:最长报文段生存时间,1~4分钟)。

https://blog.csdn.net/liujh_990807/article/details/104101726

TIME_WAIT状态的作用:

1、可靠地实现TCP的连接终止。

在终止TCP连接时有4个报文需要交换,其中最后一个ACK报文是由客户端发往服务器。假设这个ACK报文在网络中被丢弃了,那么服务器端收不到这个确认ACK,服务器端会向客户端再次发送FIN。这就是为什么TIME_WAIT状态持续2倍的最长报文段生存时间:1MSL时间留给最后的ACK确认报文段到达服务器端,1MSL时间留给服务器端再次发送的FIN(这一段摘抄自《unix系统编程手册》P1046,我不明白,超过2MSL连接就超时关闭了,再次发送FIN后,即客户端刚收到,2MSL时间也就到了,连接就关闭了,再次发送FIN的意义何在?,希望有知道的同学告诉我)。

 

2、确保老的重复的报文段在网络中过期失效,这样建立新的连接时将不再接受它们。

TCP协议采用的是出错重传,也就是会生成重复的报文,并且根据路由器的选择,这些重复的报文可能在连接终止后才到达,如果客户端/服务器端收到这个老的报文会把它误认为一个同一连接的新的报文,然后对这个报文进行处理,这样就会出现错误。从状态转换图我们可以看到从TIME_WAIT到连接终止,中间有2MSL,这个时间足以让老的重复的报文段过期失效。

  1. 保证当最后一个ack丢失后,能收到对端重传的fin包.
  2. 保证ack包消失,不会影响下一个连接.

关于原因2: 重传时间一般为几百毫秒,而延时的数量级可能为几十秒(MSL数量级),所以延迟到达的包可能是曾经的fin包或其他,如果是fin,会影响下一个连接.

TIME_WAIT会出现在服务器吗?

会的,TIME_WATI存在首先执行主动关闭的那端,比如爬虫服务器他本身其实就是客户端,完成爬取任务后,执行关闭,那么所有的TCP连接都会处于TIME_WAIT状态。

 

TIME_WAIT的危害:Linux分配给一个用户的文件句柄是有限的,如果系统中存在大量的TIME_WAIT状态,一旦达到句柄数上限,新的请求就无法被处理了,而且大量TIME_WAIT连接占用资源影响性能。

mtu是网络传输最大报文包。mss是网络传输数据最大值。mss加包头数据就等于mtu。

1、mss加包头数据就等于mtu. 简单说拿TCP包做例子。 报文传输1400字节的数据的话,那么mss就是1400,再加上20字节IP包头,20字节tcp包头,那么mtu就是1400+20+20. 当然传输的时候其他的协议还要加些包头在前面,总之mtu就是总的最后发出去的报文大小。mss就是你需要发出去的数据大小。

2、MSS: Maxitum Segment Size 最大分段大小 2.MSS最大传输大小的缩写,是TCP协议里面的一个概念。 3.MSS就是TCP数据包每次能够传输的最大数据分段。

3、为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。

 

 

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值