`
uule
  • 浏览: 6351775 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

TCP如何保证传输可靠性

 
阅读更多

 TCP 滑动窗口和 拥塞窗口

 

 

TCP协议保证数据传输可靠性的方式主要有:

(校序重流拥)

 

校验和

       发送的数据包的二进制相加然后取反,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。 

确认应答+序列号

       TCP给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。 

超时重传

       当TCP发出一个段后,它启动一个定时器等待目的端确认收到这个报文段如果不能及时收到一个确认,将重发这个报文段。 

 

流量控制

       TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP使用的流量控制协议是可变大小的滑动窗口协议。

        接收方有即时窗口(滑动窗口),随ACK报文发送

 

拥塞控制

       当网络拥塞时,减少数据的发送。

         发送方有拥塞窗口,发送数据前比对接收方发过来的即使窗口,取小

          慢启动、拥塞避免、拥塞发送、快速恢复

 

应用数据被分割成TCP认为最适合发送的数据块。 

TCP的接收端会丢弃重复的数据。 

 

 

1、校验和

计算方式:在数据传输的过程中,将发送的数据段都当做一个16位的整数。将这些整数加起来。并且前面的进位不能丢弃,补在后面,最后取反,得到校验和。 

发送方:在发送数据之前计算检验和,并进行校验和的填充。 

接收方:收到数据后,对数据以同样的方式进行计算,求出校验和,与发送方的进行比对。


 注意:如果接收方比对校验和与发送方不一致,那么数据一定传输有误。但是如果接收方比对校验和与发送方一致,数据不一定传输成功

 

2、确认应答与序列号

序列号:TCP传输时将每个字节的数据都进行了编号,这就是序列号。 

确认应答:TCP传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送ACK报文。这个ACK报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。


 

序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。这也是TCP传输可靠性的保证之一。

 

3、超时重传

在进行TCP传输时,由于确认应答与序列号机制,也就是说发送方发送一部分数据后,都会等待接收方发送的ACK报文,并解析ACK报文,判断数据是否传输成功。如果发送方发送完数据后,迟迟没有等到接收方的ACK报文,这该怎么办呢?而没有收到ACK报文的原因可能是什么呢?

 

首先,发送方没有接收到响应的ACK报文原因可能有两点

a、数据在传输过程中由于网络原因等直接全体丢包,接收方没有接收到

b、接收方接收到了响应的数据,但是发送的ACK报文响应却由于网络原因丢包了

 

TCP在解决这个问题的时候引入了一个新的机制,叫做超时重传机制。简单理解就是发送方在发送完数据后等待一个时间,时间到达没有接收到ACK报文,那么对刚才发送的数据进行重新发送。如果是刚才第一个原因,接收方收到二次重发的数据后,便进行ACK应答。如果是第二个原因,接收方发现接收的数据已存在(判断存在的根据就是序列号,所以上面说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送ACK应答。

 

那么发送方发送完毕后等待的时间是多少呢?如果这个等待的时间过长,那么会影响TCP传输的整体效率,如果等待时间过短,又会导致频繁的发送重复的包。如何权衡?

 

由于TCP传输时保证能够在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。

 

注意:

超时以500ms(0.5秒)为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。重发一次后,仍未响应,那么等待2*500ms的时间后,再次重传。等待4*500ms的时间继续重传。以一个指数的形式增长。累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。

 

 

4、连接管理

连接管理就是三次握手与四次挥手的过程,在前面详细讲过这个过程,这里不再赘述。保证可靠的连接,是保证可靠性的前提。

 

4.1 流量控制

接收端在接收到数据后,对其进行处理。如果发送端的发送速度太快,导致接收端的结束缓冲区很快的填充满了。此时如果发送端仍旧发送数据,那么接下来发送的数据都会丢包,继而导致丢包的一系列连锁反应,超时重传呀什么的。而TCP根据接收端对数据的处理能力,决定发送端的发送速度,这个机制就是流量控制。

 

在TCP协议的报头信息当中,有一个16位字段的窗口大小。在介绍这个窗口大小时我们知道,窗口大小的内容实际上是接收端接收数据缓冲区的剩余大小。这个数字越大,证明接收端接收缓冲区的剩余空间越大,网络的吞吐量越大。接收端会在确认应答发送ACK报文时,将自己的即时窗口大小填入,并跟随ACK报文一起发送过去发送方根据ACK报文里的窗口大小的值的改变进而改变自己的发送速度。如果接收到窗口大小的值为0,那么发送方将停止发送数据。并定期的向接收端发送窗口探测数据段,让接收端把窗口大小告诉发送端。 


 注:16位的窗口大小最大能表示65535个字节(64K),但是TCP的窗口大小最大并不是64K。在TCP首部中40个字节的选项中还包含了一个窗口扩大因子M,实际的窗口大小就是16为窗口字段的值左移M位。每移一位,扩大两倍。

 

4.2 拥塞控制

TCP传输的过程中,发送端开始发送数据的时候,如果刚开始就发送大量的数据,那么就可能造成一些问题。网络可能在开始的时候就很拥堵,如果给网络中在扔出大量数据,那么这个拥堵就会加剧。拥堵的加剧就会产生大量的丢包,就对大量的超时重传,严重影响传输。

 

所以TCP引入了慢启动的机制,在开始发送数据时,先发送少量的数据探路。探清当前的网络状态如何,再决定多大的速度进行传输。这时候就引入一个叫做拥塞窗口的概念。发送刚开始定义拥塞窗口为 1,每次收到ACK应答,拥塞窗口加 1。在发送数据之前,首先将拥塞窗口与接收端反馈的窗口大小比对,取较小的值作为实际发送的窗口。

 

拥塞窗口的增长是指数级别的。慢启动的机制只是说明在开始的时候发送的少,发送的慢,但是增长的速度是非常快的。为了控制拥塞窗口的增长,不能使拥塞窗口单纯的加倍,设置一个拥塞窗口的阈值,当拥塞窗口大小超过阈值时,不能再按照指数来增长,而是线性的增长。在慢启动开始的时候,慢启动的阈值等于窗口的最大值,一旦造成网络拥塞,发生超时重传时慢启动的阈值会为原来的一半(这里的原来指的是发生网络拥塞时拥塞窗口的大小),同时拥塞窗口重置为 1。 


 

拥塞控制是TCP在传输时尽可能快的将数据传输,并且避免拥塞造成的一系列问题。是可靠性的保证,同时也是维护了传输的高效性。

 

拥塞控制主要是四个算法:1)慢启动,2)拥塞避免,3)拥塞发生,4)快速恢复。

 

拥塞避免

当拥塞窗口 >= 阀值时,就会进入“拥塞避免算法”。

这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。是一个线性上升的算法。

 

拥塞发生

当发生超时重传后,阀值会变成拥塞窗口的一半

 

快速恢复

 

================================================================================

TCP滑动窗口

 

需要说明一下,如果你不了解TCP的滑动窗口这个事,你等于不了解TCP协议。我们都知道,TCP必需要解决的可靠传输以及包乱序(reordering)的问题,所以,TCP必需要知道网络实际的数据处理带宽或是数据处理速度,这样才不会引起网络拥塞,导致丢包。

 

所以,TCP引入了一些技术和设计来做网络流控,Sliding Window是其中一个技术。 前面我们说过,TCP头里有一个字段叫Window,又叫Advertised-Window,这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。 为了说明滑动窗口,我们需要先看一下TCP缓冲区的一些数据结构:



 

上图中,我们可以看到:

 

1、接收端LastByteRead指向了TCP缓冲区中读到的位置,NextByteExpected指向的地方是收到的连续包的最后一个位置,LastByteRcved指向的是收到的包的最后一个位置,我们可以看到中间有些数据还没有到达,所以有数据空白区。

2、发送端的LastByteAcked指向了被接收端Ack过的位置(表示成功发送确认),LastByteSent表示发出去了,但还没有收到成功确认的Ack,LastByteWritten指向的是上层应用正在写的地方。

 

于是:

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

b、而发送方会根据这个窗口来控制发送数据的大小,以保证接收方可以处理。

下面我们来看一下发送方的滑动窗口示意图:


 上图中分成了四个部分,分别是:(其中那个黑模型就是滑动窗口

 

#1已收到ack确认的数据。

#2已发出但还没收到ack的

#3在窗口中还没有发出的(接收方还有空间)

#4窗口以外的数据(接收方没空间)

 

注意:

滑动窗口里是 已发出但未收到ACk、还未发出的 数据

 

下面是个滑动后的示意图(收到36的ack,并发出了46-51的字节):


 下面我们来看一个接受端控制发送端的图示:



 

=====================================================================

问题:

TCP是以段为单位进行数据包的发送的。

(1)在建立TCP连接的同时,也可以确定发送数据包的单位,称之为“最大消息长度”:MSS。最理想的情况是,最大消息长度MSS正好是IP层中不被分片处理的最大数据长度。

(2)TCP在传送大量数据的时候,是以“段=MSS的大小”将数据进行分割发送的,进行重发时也是以MSS为单位的。

(3)最大消息长度——MSS是在三次握手的时候,在两端主机之间被计算得出的。两端主机在发出“建立TCP连接请求的SYN包”时,会在SYN包的TCP首部中写入MSS选项,告诉对方自己所能够适应的MSS的大小,然后发送端主机会在两者之间选择一个较小的MSS值投入使用。

 

 

TCP为什么引入接受缓存这个数据结构?

如果没有接受缓存的话,或者说只有一个缓存的话,为了保证接受的数据是按顺序传输的,所以如果位于x序号之后的序号分组先到达目的主机的运输层的话必然丢弃,这样的话将在重传上花费很大的开销,所以一般如果有过大的序号达到接收端,那么会按照序号缓存起来等待之前的序号分许到达,然后一并交付到应用进程。

 

TCP 粘包/拆包的原因及解决方法

TCP是以流的方式来处理数据,一个完整的包可能会被TCP拆分成多个包进行发送也可能把小的封装成一个大的数据包发送。

 

TCP粘包/分包的原因:

应用程序写入的字节大小大于套接字发送缓冲区的大小,会发生拆包现象,而应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包现象;

进行MSS大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包

以太网帧的payload(净荷)大于MTU(1500字节)进行ip分片。

 

解决方法

消息定长:FixedLengthFrameDecoder类

包尾增加特殊字符分割:行分隔符类:LineBasedFrameDecoder或自定义分隔符类 :DelimiterBasedFrameDecoder

将消息分为消息头和消息体:LengthFieldBasedFrameDecoder类。分为有头部的拆包与粘包、长度字段在前且有头部的拆包与粘包、多扩展头部的拆包与粘包。

 

 

利用滑动窗口控制提高速度

(1)TCP是以一个段为单位进行数据的传输的,每发送一个段,就会等待对端主机的针对这个段的确认应答信号ACK,但这样的传输方式的缺点也很明显,就是:当数据包的往返时间越长,通信性能越低

(2)为了解决这个问题,TCP引入了窗口这个概念,即使在往返时间比较长的情况下,它也能够控制网络性能的下降。

确认应答包不再以每个段为单位进行确认了,而是以更大的单位进行确认,转发时间将会被大幅度的缩短。也就是说,发送端主机在发送了一个段之后,没必要一直等待对端主机的确认应答信号,而是继续发送。

(3)窗口大小,指的就是无需等待接收端主机的确认应答信号而可以持续发送的数据的最大值,或者说段的最大值。滑动窗口控制的实现,使用了大量的缓冲区,通过对多个段的数据同时进行确认应答来实现高效传输。

(4)发送数据中的高亮部分正是前面提到的窗口。在这个窗口内的数据即便没有收到确认应答也可以发送出去,此外发送端主机在等到对端主机的确认应答之前,必须在缓冲区中保留这部分数据,以便数据包的丢失而重发。

(5)在滑动窗口以外的数据,包括尚未发送出去的数据,以及已经确认对端收到的数据,当发送端确认对端已经收到数据包之后,此数据包就可以从缓冲区中清除了。

 

当收到确认应答信号过之后,会把滑动窗口的位置滑动到确认应答的序列号的位置,这样就可以顺序的将多个段同时发送以提高通信功能了。这就是滑动窗口控制。

 

 

 

 

  • 大小: 11.3 KB
  • 大小: 23 KB
  • 大小: 29.1 KB
  • 大小: 88.3 KB
  • 大小: 33.1 KB
  • 大小: 36.2 KB
  • 大小: 24 KB
  • 大小: 62.9 KB
分享到:
评论

相关推荐

    TCP/IP可靠数据传输代码实现

    首先,TCP通过建立连接来确保数据传输的可靠性,这个过程被称为三次握手。在代码实现中,我们需要创建socket对象,然后通过send和recv函数发送和接收数据。三次握手涉及SYN(同步序列编号)和ACK(确认)标志的交换...

    TCP文件传输服务器

    TCP通过确认机制和重传策略保证了数据的可靠性。如果在传输过程中发生丢包,TCP会自动请求重传丢失的数据段,直到所有数据成功到达。因此,即使在网络条件不稳定的情况下,服务器也能接收到完整的文件。 在VS2015中...

    MFC实现TCP数据传输

    TCP是一种面向连接、可靠的网络协议,确保数据在互联网上按顺序、无丢失地传递。 首先,实现TCP数据传输的关键在于理解套接字(Socket)编程。在MFC中,你可以使用CSocket类来创建和管理套接字。创建一个CSocket...

    tcp 文件可靠传输

    在TCP文件传输中,确保数据的可靠性是关键,这包括了数据的顺序传输、错误检测与纠正以及流量控制等多个方面。 首先,TCP建立连接的过程称为三次握手(Three-Way Handshake)。客户端发送一个SYN(同步序列编号)包...

    TCP文件传输实现

    总的来说,通过研究这个项目,你可以深入理解TCP套接字编程,包括如何创建和管理Socket,如何处理输入输出流,以及如何利用TCP的特性确保文件传输的可靠性和效率。同时,控制台应用的实现方式也使得整个过程更加直观...

    TCP.rar_TCP 传输_TCP 文件传输_socket+文件传输_tcp文件传输_文件传输 C

    1. **TCP传输**:TCP是网络通信中用于传输数据的主要协议,它通过三次握手建立连接,并使用序列号和确认应答来保证数据的可靠传输。 2. **文件传输**:TCP常用于文件传输,因为它可以确保文件在传输过程中的完整性...

    opencv tcp 视频传输

    2. TCP协议:确保数据的可靠传输,包括数据包的顺序和完整性保证。 3. 图像数据在网络中的传输:图像帧被分割成数据包,通过TCP套接字发送。 4. 接收端的数据重组:服务器接收数据包并按顺序重组,使用`cv2.imdecode...

    TCP及其可靠性分析

    通过对TCP段格式的理解以及TCP连接建立与拆除流程的学习,我们可以更深入地理解TCP是如何保证数据传输的可靠性的。在未来的发展中,随着网络技术的进步,TCP协议也会不断优化和发展,更好地适应日益复杂的网络环境。

    基于TCP的文件传输

    基于TCP的文件传输是通过TCP协议的可靠性和顺序性保证文件的安全、完整传输。QQ作为典型的TCP应用,其文件传输功能利用了TCP的各种优势,如连接可靠性、流量控制和优化策略,同时考虑了安全性,确保了用户文件的高效...

    TCP文件传输系统.zip

    TCP协议保证了数据的有序性和可靠性,通过序号和确认号确保每个数据段都能正确到达,同时通过重传机制处理丢包问题。 3. 流量控制:TCP协议内置了流量控制机制,通过滑动窗口机制限制发送方的数据速率,防止接收方...

    Qt_TCP传输文件

    TCP的可靠性和顺序性保证了文件的完整性和一致性。 **三、创建TCP服务器** 1. 首先,实例化QTcpServer,并设置一个槽函数处理新的客户端连接。 2. 当有客户端连接时,QTcpServer会触发newConnection()信号,此时...

    用tcp协议传输文件

    在TCP协议中,数据被分成多个数据段进行传输,并通过序列号、确认应答、重传机制等确保数据的正确性和完整性,为文件传输提供了稳定的基础。 在实现TCP协议传输文件的过程中,我们需要遵循以下几个关键步骤: 1. *...

    Tcp可靠传输flash动画

    TCP(Transmission ...通过这样的视觉化展示,学习者能够更直观地看到TCP如何保证数据的可靠性,理解TCP协议背后的工作原理。而`.fla`和`.swf`文件是Flash动画的源文件和可执行文件,分别用于编辑和查看动画内容。

    C#通过TCP传输文件.rar_C#网口传输_tcp_tcp传输文件c#_文件传输_服务端与

    总之,C#通过TCP传输文件涉及网络编程基础、数据序列化和流操作等多个知识点,理解并熟练掌握这些技能,对于开发高效、可靠的网络应用程序至关重要。通过实际操作和学习提供的源代码,能更好地巩固理论知识并提升...

    tcp文件传输助手.zip

    3. **错误处理和确认**:为了保证可靠性,每次发送数据后,服务器都需要发送一个确认应答,客户端也需要检查接收的数据是否正确,有无丢失或错误。 4. **断开连接**:文件传输完成后,双方需要通过四次挥手断开连接...

    C++实现的TCP协议的文件传输

    在TCP传输中,我们需要将文件内容拆分成多个数据块,逐个发送。 6. **数据发送与接收**:使用`send()`或`write()`函数发送数据,`recv()`或`read()`函数接收数据。TCP协议不保证一次发送的数据能一次性接收,因此...

    基于TCP的文件传输器

    9. **安全性考虑**:虽然TCP提供了可靠性,但不保证安全性。在实际应用中,可能需要使用SSL/TLS等加密技术,以保护文件传输过程中的数据安全。 10. **性能优化**:根据网络条件,可能需要调整TCP窗口大小、使用慢...

    TCP文件传输

    尽管TCP本身提供了数据的可靠性,但并不保证数据的安全性。因此,实际应用中,可能需要结合SSL/TLS等安全协议来加密传输数据,防止数据在传输过程中被窃取或篡改。 总的来说,通过这次C#的TCP文件传输课后作业,...

    基于C#的tcp图像传输

    在图像传输中,TCP的可靠性尤为重要,因为图像数据的任何丢失都可能导致显示质量下降甚至无法正常显示。 在C#中实现TCP图像传输,通常会涉及以下关键步骤和知识点: 1. **创建服务器端**:首先,我们需要创建一个...

Global site tag (gtag.js) - Google Analytics