网络通信之tcp协议有哪些_基于tcp协议的协议

网络通信之tcp协议有哪些_基于tcp协议的协议TCP是一个巨复杂的协议,在网络通信中他需要解决很多问题,所以这里是带着大家来了解TCP协议的魅力,关于协议的细节,推荐去看W.RichardStevens的《TCP/IP详解卷1:协议》

TCP是一个巨复杂的协议,在网络通信中他需要解决很多问题,所以这里是带着大家来了解TCP协议的魅力,关于协议的细节,推荐去看W.Richard Stevens的《TCP/IP 详解 卷1:协议》。

一. tcp概念

TCP四元组:[源ip,源端口号,目的ip,目的端口号]


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

三个概念:

面向连接:必须在建立连接前确认对方链路可达并准备好才开始通信,建立后对状态的保持。(udp直接通信,不会询问接收端是否可达并准备接收数据)

字节流:tcp传输的是byte类型数据。

可靠:保证数据报能够到达接收端(超时重传机制、丢包重传及数据顺序一致)(真的一定可靠吗?)

 

二. tcp如何建立连接

2.1 两军问题

本质:在不可靠的通信链路上试图通过通信达成一致。

网络通信之tcp协议有哪些_基于tcp协议的协议

问题描述:一支白军被围困在一个山谷中,山谷的两侧是蓝军。困在山谷中的白军人数多余山谷两侧的任意一支蓝军,而少于两支蓝军的中和。若一支蓝军对白军单独发起进攻,则必败无疑;但若两支蓝军同时发起进攻,则可取胜。两只蓝军希望同时发起进攻,这样他们就要传递消息,以便确定发起进攻的具体时间。假设他们只能派遣士兵穿越白军所在的山谷(唯一的通信信道)来传递消息,那么在穿越山谷是,士兵有可能被俘虏,从而造成消息的丢失。现在的问题是:如何通信,以便蓝军必胜。

通信策略:

网络通信之tcp协议有哪些_基于tcp协议的协议

最后发出消息的一方永远不知道对方是否收到这个消息,因此不存在使蓝队必胜的通信协议。

结论在不可靠的通信中,不管几次握手都是有风险的。因为永远无法确定最后一次通信送达。通信次数大于3后并不能提升通信的可靠性。这是tcp采用三次握手的原因。

2.2 tcp的报文格式

网络通信之tcp协议有哪些_基于tcp协议的协议

tcp标志位

ACK:确认标志位,确认可以发送数据,建立连接后act为1。

SYN:建立连接标志位,在连接建立时用来同步序号,syn为1表示这是一个连接请求或连接接收报文。

FIN:结束一个连接的标志位,FIN=1表示释放连接。

URG:当URG=1时,表示报文段中有紧急数据,应尽快传送。

 PSH:当发送端PSH=1时,接收端尽快的交付给应用进程。

 RST:当RST=1时,表明TCP连接中出现严重差错,必须释放连接,再重新建立连接。

其他数据

序   号seq:tcp建立连接是会随机生成一个序号,建立连接后tcp进行通信全部是基于这个序号(也是tcp传输数据顺序一致的保证)。

确认号ack:接受端确认收到数据对seq加一。

窗口:用来控制对方发送的数据量,通知发放已确定的发送窗口上限。

2.3 tcp三次握手

网络通信之tcp协议有哪些_基于tcp协议的协议

三次握手的过程:

客户端主动打开连接,发送ACT=0,SYN=1表示请求建立连接,产生随机数x为序号seq,给服务器发起第一次握手;

服务器接收到客户端的请求后,发送SYN=1,ACK=1表示连接到接收报文,确认号act=x+1表示知道了客户端的seq,同时产生服务器的随机数y作为序号seq,发送给客户端,即为第二次握手;

最后客户端设置AC=1表示建立请求,设置act=y+1,seq=x+1表示发送的确认消息。即为第三次握手。

经过这三个步骤后,客户端也服务器通过三次握手建立起tcp连接。

三. tcp如何保证可靠性

tcp建立了ip协议之上,ip协议只提供在源地址和目的地址之间传输数据包,并不负责保证数据的可靠性。而tcp通过一系列的机制保证了传输的可靠性。

3.1 数据顺序一致性

网络通信之tcp协议有哪些_基于tcp协议的协议

TCP报文依赖IP分组传输,IP分组的到达可能失去顺序,tcp通过tcp报文中的序号seq标记了数据的发送顺序,在目的端对接收的tcp报文按照seq重新排序,然后提交给应用层,从而保证了应用层收到的数据是有序一致的。

网络通信之tcp协议有哪些_基于tcp协议的协议

3.2 重传机制

tcp需要保证所有数据包都可以到达,所以需要提供重传机制。

网络通信中可能会因为网络不好、超时等原因导致出现丢包,如何解决网络丢包问题?tcp采用接收端通过ack来告知发送端前面的ack-1个字节已经被接受了,未被确认了报文在超时后进行重发。

网络通信之tcp协议有哪些_基于tcp协议的协议

接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,于是回ack 2,然后收到了3、4、5(注意此时2没收到),tcp怎么处理?(tcp不能跳着确认,只能确认最大接收到的连续的包,不然会被认为之前的都收到了)

3.2.1 超时重传机制

网络通信之tcp协议有哪些_基于tcp协议的协议

不回ack,死等2,当发送端发现收不到2的ack超时后,会重传2,一旦接收方收到2,会ack回6,就意味着2、3、4、5都收到了。但是这也会让发送端认为3、4、5都丢了,导致3、4、5都重传。对此有两个方案:

  1. 是重传timeout的第一个包(重传2) 可以节省带宽,但是慢,因为你不知道是2接收到还是2、3、4、5中还有其他没接收到。
  2. 还是重传接下来所有数据(重传2、3、4、5)?  快一些,但是浪费带宽。
3.2.2 快速重传机制

TCP引入了一种叫Fast Retransmit 的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。

网络通信之tcp协议有哪些_基于tcp协议的协议

同样是刚才的数据包,收到3、4、5的数据后,接收端给发送端返回ack=2的确认,根据快速重传机制,发送端知道了2还没有到达,于是不等timeout。马上重传2,然后接收端收到了2,由于之前就接收到3、4、5,于是返回ack=6。

Fast Retransmit只解决了一个问题,就是timeout的问题,它依然面临一个艰难的选择,就是,是重传之前的一个还是重传所有的问题。

3.2.3 TCP SACK

对于上面那个问题,TCP提供了Selective Acknowledgment (SACK)方法,这种方式需要在TCP头里加一个SACK的东西,ACK还是Fast Retransmit的ACK,SACK则是汇报收到的数据碎版。

网络通信之tcp协议有哪些_基于tcp协议的协议

接收端的ack仍然返回连续最大的确认值,在sack中返回接收端接收到的大于ack的信息,如上图,300-499的数据没有接收到,但是接收到500-699的数据,此时接收端发送ack=300,sack为500-700的返回消息,当返回消息三次都为ack=300时,发送端就可以知道300-499的数据没有接收到,发送端就可以只重传300-499的数据了。

此外,还有ack丢包,网络延时的问题。

3.3 流量控制

解决了传输可靠性的问题,接下来还有一个很大的问题,如何在一个网络中根据不同的情况来动态调整自己的发包速度。

网络通信之tcp协议有哪些_基于tcp协议的协议

从tcp的重传机制中,我们知道Fast Retransmit和timeout是决定重传的两个因素。Fast Retransmit好定制,但是timeout的设置就很麻烦,因为在不同的网络环境下,timeout本身就不是一个定值,只能动态的设置,为了动态设置timeout,tcp引入了RTT(Round Trip Time)算法。Round Trip Time就是一个数据包从发出去到回来的时间。这样发送端就大约知道需要多少的时间,从而可以方便地设置Timeout——RTO(Retransmission TimeOut),以让我们的重传机制更高效。 

3.3.1 RTT算法
  • 1)首先,先采样RTT,记下最近好几次的RTT值。
  • 2)然后做平滑计算SRTT( Smoothed RTT),公式为:(其中的 α 取值在0.8 到 0.9之间,这个算是加权移动平均)
         SRTT = ( α * SRTT ) + ((1- α) * RTT)
  • 3)开始计算RTO。公式如下:
         RTO = min [ UBOUND,  max [ LBOUND,   (β * SRTT) ]  ]

UBOUND是最大的timeout时间,上限值

LBOUND是最小的timeout时间,下限值

β 值一般在1.3到2.0之间。

3.3.2 Karn / Partridge 算法

但是RTT算法在重传的时候会出有一个终极问题——你是用第一次发数据的时间和ack回来的时间做RTT样本值,还是用重传的时间和ACK回来的时间做RTT样本值?

网络通信之tcp协议有哪些_基于tcp协议的协议

一种情况是ack没回来,所以重传。如果你计算第一次发送和ACK的时间,那么,明显算大了。另外一种情况是ack回来慢了,但是导致了重传,但刚重传不一会儿,之前ACK就回来了。如果你是算重传的时间和ACK回来的时间的差,就会算短了。

Karn / Partridge 算法对这个问题的解决方法忽略重传,不把重传的RTT做采样。而只要一发生重传,就对现有的RTO值翻倍(这就是所谓的 Exponential backoff)。

3.3.3 Jacobson / Karels 算法

Karn / Partridge 算法发生重传就翻倍的方式对RTT的估算也不准确,而“加权移动平均”如果RTT有一个大的波动的话,很难被发现,因为被平滑掉了。Jacobson / Karels 算法引入了最新的RTT的采样和平滑过的SRTT的差距做因子来计算。 

  • SRTT = SRTT + α (RTT – SRTT) :计算平滑RTT;
  • DevRTT = (1-β)*DevRTT + β*(|RTT-SRTT|) :计算平滑RTT和真实的差距(加权移动平均);
  • RTO= μ * SRTT + ∂ *DevRTT 

在Linux下,α = 0.125,β = 0.25, μ = 1,∂ = 4 ,而这个算法在被用在今天的TCP协议中。

3.4 滑动窗口

确定了tcp的超时重传时间timeout后,tcp需要解决的是网络实际的数据处理速度。这样才不会引起网络拥塞,导致丢包。

TCP头里有一个字段叫Window,又叫Advertised-Window,这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。

tcp缓冲区结构

网络通信之tcp协议有哪些_基于tcp协议的协议

接收端LastByteRead指向了TCP缓冲区中读到的位置,NextByteExpected指向的地方是收到的连续包的最后一个位置,LastByteRcved指向的是收到的包的最后一个位置,我们可以看到中间有些数据还没有到达,所以有数据空白区。
发送端的LastByteAcked指向了被接收端Ack过的位置(表示成功发送确认),LastByteSent表示发出去了,但还没有收到成功确认的Ack,LastByteWritten指向的是上层应用正在写的地方。

接收端在给发送端回ACK中会汇报自己的AdvertisedWindow = MaxRcvBuffer – LastByteRcvd – 1。

发送端滑动窗口示意图

网络通信之tcp协议有哪些_基于tcp协议的协议

send window就是滑动窗口

  • 1. Sent and Acknowledged:这些数据表示已经发送成功并已经被确认的数据,比如图中的前31个bytes,这些数据其实的位置是在窗口之外了,因为窗口内顺序最低的被确认之后,要移除窗口,实际上是窗口进行合拢,同时打开接收新的带发送的数据
  • 2. Send But Not Yet Acknowledged:这部分数据称为发送但没有被确认,数据被发送出去,没有收到接收端的ACK,认为并没有完成发送,这个属于窗口内的数据。
  • 3. Not Sent,Recipient Ready to Receive:这部分是尽快发送的数据,这部分数据已经被加载到缓存中,也就是窗口中了,等待发送,其实这个窗口是完全有接收方告知的,接收方告知还是能够接受这些包,所以发送方需要尽快的发送这些包
  • 4. Not Sent,Recipient Not Ready to Receive: 这些数据属于未发送,同时接收端也不允许发送的,因为这些数据已经超出了发送端所接收的范围

网络通信之tcp协议有哪些_基于tcp协议的协议

接收端的数据有3个分类,因为接收端并不需要等待ACK所以它没有类似的接收并确认了的分类

网络通信之tcp协议有哪些_基于tcp协议的协议

情况如下

  • 1.  Received and ACK Not Send to Process:这部分数据属于接收了数据但是还没有被上层的应用程序接收,也是被缓存在窗口内
  • 2.  Received  Not ACK: 已经接收并,但是还没有回复ACK,这些包可能输属于Delay ACK的范畴了
  • 3.  Not Received:有空位,还没有被接收的数据。

3.5 拥塞控制

有了重传机制和流量控制,tcp协议已经很完善了。但是还有一个问题,如果网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,但是,重传会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,于是,这个情况就会进入恶性循环被不断地放大。试想一下,如果一个网络内有成千上万的TCP连接都这么行事,那么马上就会形成“网络风暴”,TCP这个协议就会拖垮整个网络。

所以,tcp需要知道网络上发生的事情,不能无脑的重发数据,对整个网络造成更大的伤害。将TCP设计成一个无私的协议,当拥塞发生的时候,要做自我牺牲。就像交通阻塞一样,每个车都应该把路让出来,而不要再去抢路了。

拥塞控制主要是四个算法:

  • 1)慢启动;
  • 2)拥塞避免;
  • 3)拥塞发生;
  • 4)快速恢复。
 3.5.1 慢启动算法

慢启动的算法如下(cwnd全称Congestion Window):

1)连接建好的开始先初始化cwnd = 1,表明可以传一个MSS大小的数据。

2)每当收到一个ACK,cwnd++; 呈线性上升

3)每当过了一个RTT,cwnd = cwnd*2; 呈指数让升

4)还有一个ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”。

网络通信之tcp协议有哪些_基于tcp协议的协议

3.5.2 拥塞避免算法

当cwnd >= ssthresh时,就会进入“拥塞避免算法”。当cwnd达到这个值时后,算法如下:

1)收到一个ACK时,cwnd = cwnd + 1/cwnd

2)当每过一个RTT时,cwnd = cwnd + 1

这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。

3.5.3 拥塞发生算法

当丢包的时候,会有两种情况:

1)等到RTO超时,重传数据包。TCP认为这种情况太糟糕,反应也很强烈。

    • sshthresh =  cwnd /2
    • cwnd 重置为 1
    • 进入慢启动过程

2)Fast Retransmit算法,也就是在收到3个duplicate ACK时就开启重传,而不用等到RTO超时。

    • TCP Tahoe的实现和RTO超时一样。
    • TCP Reno的实现是:
      • cwnd = cwnd /2
      • sshthresh = cwnd
      • 进入快速恢复算法——Fast Recovery

上面我们可以看到RTO超时后,sshthresh会变成cwnd的一半,这意味着,如果cwnd<=sshthresh时出现的丢包,那么TCP的sshthresh就会减了一半,然后等cwnd又很快地以指数级增涨爬到这个地方时,就会成慢慢的线性增涨。我们可以看到,TCP是怎么通过这种强烈地震荡快速而小心得找到网站流量的平衡点的。

3.5.4 快速恢复算法

TCP Reno

快速重传和快速恢复算法一般同时使用。快速恢复算法是认为,你还有3个Duplicated Acks说明网络也不那么糟糕,所以没有必要像RTO超时那么强烈。 注意,正如前面所说,进入Fast Recovery之前,cwnd 和 sshthresh已被更新:

  • cwnd = cwnd /2
  • sshthresh = cwnd

然后,真正的Fast Recovery算法如下:

  • cwnd = sshthresh  + 3 * MSS (3的意思是确认有3个数据包被收到了)
  • 重传Duplicated ACKs指定的数据包
  • 如果再收到 duplicated Acks,那么cwnd = cwnd +1
  • 如果收到了新的Ack,那么,cwnd = sshthresh ,然后就进入了拥塞避免的算法了。

如果你仔细思考一下上面的这个算法,你就会知道,上面这个算法也有问题,那就是——它依赖于3个重复的Acks。注意,3个重复的Acks并不代表只丢了一个数据包,很有可能是丢了好多包。但这个算法只会重传一个,而剩下的那些包只能等到RTO超时,于是,进入了恶梦模式——超时一个窗口就减半一下,多个超时会超成TCP的传输速度呈级数下降,而且也不会触发Fast Recovery算法了。

通常来说,正如我们前面所说的,SACK或D-SACK的方法可以让Fast Recovery或Sender在做决定时更聪明一些,但是并不是所有的TCP的实现都支持SACK(SACK需要两端都支持),所以,需要一个没有SACK的解决方案。而通过SACK进行拥塞控制的算法是FACK(后面会讲)

TCP New Reno

于是,1995年,TCP New Reno(参见 RFC 6582 )算法提出来,主要就是在没有SACK的支持下改进Fast Recovery算法的——

  • 当sender这边收到了3个Duplicated Acks,进入Fast Retransimit模式,开发重传重复Acks指示的那个包。如果只有这一个包丢了,那么,重传这个包后回来的Ack会把整个已经被sender传输出去的数据ack回来。如果没有的话,说明有多个包丢了。我们叫这个ACK为Partial ACK。
  • 一旦Sender这边发现了Partial ACK出现,那么,sender就可以推理出来有多个包被丢了,于是乎继续重传sliding window里未被ack的第一个包。直到再也收不到了Partial Ack,才真正结束Fast Recovery这个过程

我们可以看到,这个“Fast Recovery的变更”是一个非常激进的玩法,他同时延长了Fast Retransmit和Fast Recovery的过程。

网络通信之tcp协议有哪些_基于tcp协议的协议 

 

四. Wireshark抓包工具

 Wireshark 是最著名的网络通讯抓包分析工具。功能十分强大,可以截取各种网络封包,显示网络封包的详细信息。

网络通信之tcp协议有哪些_基于tcp协议的协议

抓到的一个包,tcp报文对应关系

网络通信之tcp协议有哪些_基于tcp协议的协议

4.1 Wireshark 中的三次握手 

第一次握手

网络通信之tcp协议有哪些_基于tcp协议的协议

网络通信之tcp协议有哪些_基于tcp协议的协议

第二次握手

网络通信之tcp协议有哪些_基于tcp协议的协议

网络通信之tcp协议有哪些_基于tcp协议的协议

第三次握手

网络通信之tcp协议有哪些_基于tcp协议的协议

网络通信之tcp协议有哪些_基于tcp协议的协议

4.2 Wireshark 中的请求过程

发起http请求

网络通信之tcp协议有哪些_基于tcp协议的协议

服务器ack确认

网络通信之tcp协议有哪些_基于tcp协议的协议

服务器返回数据

网络通信之tcp协议有哪些_基于tcp协议的协议

客户端的ack确认

网络通信之tcp协议有哪些_基于tcp协议的协议

五. tcp传输数据

tcp缓冲区简单模型

网络通信之tcp协议有哪些_基于tcp协议的协议

socket如何通过tcp读写数据

当应用希望写数据时,并不是直接向网卡驱动发数据,而是先放入到一个缓冲区中,然后根据一定算法(达到一定数量或者调用flush之后),缓冲区中的数据就经发送到网卡中了(这里说的不准确,实际上,是网卡主动从缓冲区中拷贝出来的,但并不影响我们理解)。

 

当网卡收到数据时,数据包要先经过如下几步:

  1. 数据包要先经过网卡校验正确与否。
  2. 数据链路层根据报头的类型传给不同的上层类型(IP层或者其他),并移除了数据链路层报头。
  3. IP层也需要先校验,然后根据IP报头选择不同的类型(TCP或者UDP),然后移除IP层报头,并将剩余的数据发送到相应的处理程序(tcp或udp)
  4. 到了tcp层,处理程序此时根据tcp首部中的端口号选择一个socket,并将其载荷数据拷贝进去。

tcp发送数据的结构图
网络通信之tcp协议有哪些_基于tcp协议的协议

六. udp与tcp

UDP协议全称是用户数据报协议 ,是一种无连接的协议。不提供数据包分组、组装和不能对数据包进行排序。

每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。

UDP:当套接口接收缓冲区满时,新来的数据报无法进入接收缓冲区,此数据报就被丢弃。UDP是没有流量控制的;快的发送者可以很容易地就淹没慢的接收者,导致接收方的UDP丢弃数据报。

q:我们能否用udp实现可靠的网络通信?



今天的文章网络通信之tcp协议有哪些_基于tcp协议的协议分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/66573.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注