计算机网络05--从零开始学

1.学习目标

    端口和套接字的意义

   无连接的UDP的特点

   面向连接的TCP的特点

   在不可靠的网络上实现可靠传输的工作原理,停止等待协议和ARQ协议

   TCP的滑动窗口,流量控制,拥塞控制和连接管理

2.回顾一下运输层的主要任务

负责向两台主机进程通信提供通信的数据传输服务。传输层的通用性指的是多个应用层可以使用同一个传输层,传输层的复用指的是多个应用进程可同时使用下面运输层的服务。传输层的分用是把收到的信息分别交付到应用层不同的进程中。

    传输层的两种协议

     Tcp: TCP的英文全称为:Transmission Control Protocol,TCP是面向连接的,提供可靠的交互服务。每一条TCP连接唯一被通信的两端的两个套接字所确定。传输数据的单位是报文段。

     UDP的英文全称为:User Datagram Protocol,它是面向无连接的,不提供可靠交付,但是提供尽最大可能的交付。传输数据的单位是用户数据报。

运输层向他上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是用户功能的最底层。

网络层为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。运输层还要对收到的报文进行差错检测,在网络层,ip数据报首部中的检验和字段,只检验首部是否出现差错而不检查数据部分。根据应用层序的不同需求,运输层需要有两种不同的运输协议,面向连接的TCP和无连接的UDP。

当运输层采用面向连接的TCP协议时,尽管下面的网络不可靠,即只提供最大努力的服务,他只查差,而不纠错,但是这种逻辑通信信道就相当于一条全双工的可靠信道,即错了就重传。当采用UDP协议的时候,这种逻辑通信信道是一条不可靠信道,即错了就错了。

UDP在传送数据之前,不需要先建立连接,远地主机的运输层收到UDP报文以后,不需要给出任何确认。在某些情况下UDP是一种最有效的工作方式。

TCP则提供面向连接的服务,在传送数据之前必须先建立连接,数据传送结束后要释放连接,TCP不提供广播或多播服务,Tcp要提供可靠的服务因此就不可避免地增加了许多的开销,这不仅使协议数据单元的首部增大很多,而且还占用许多的处理机资源。

3.协议端口是用来干嘛的?

保证运输层的服用和分用功能,应用层所用的应用进程都可以通过运输层再传送到ip层,这就是复用,运输层从ip收到发送给各应用进程的数据后,必须分别交付指明的各应用进程这就是分用。当运输层收到IP层交上来的运输层报文时,就能够根据其首部中的目的端口把数据交付给应用层的目的应用进程。端口总共允许有65535个。

 端口又分为服务器端使用端口和客户端使用端口

服务器端使用端口又分为系统端口(1—1023)和登记端口(1024—49151)客户端使用的端口仅在客户端进程运行时才动态选择端口。

4.无连接的UDP的特点:用户数据报协议UDP:

用户数据报协议UDP只在ip数据报服务之上增加了很少的一点功能,这就是复用和分用的功能以及差错检测的功能。

  1. UDP是无连接的,即发送数据之前不需要建立连接因此减少了开销和发送数据之前的时延。
  2. UDP使用尽最大努力交付,即不保证可靠的交付,因此主机不需要维持复杂的连接状态表。
  3. UDP是面向报文的,如何理解这一句话?UDP对应用层传下来的报文,既不合并也不才分,交给UDP多长UDP就发送多长,即一次发送一个报文,如果报文太长,UDP把他交给ip层以后,IP层在进行传送的时候可能要进行分片,这样会降低ip层的效率,反之若报文太短,UDP把他交给ip层以后,会使IP数据报的首部相对较大,这也会降低ip层的传输效率。
  4. UDP没有拥塞控制,即网络出现拥塞的时候,他不会使源主机的发送速率降低,这对某些实时应用是很重要的,允许网络拥塞时丢失一些数据,却不允许数据由太大的时延。
  5. UDP支持一对一,一对多,多对一,多对多的交互通信。UDP的首部开销小只有8个字节,比TCP的20个字节的首部要短。

用户数据报UDP有两个字段,数据字段和首部字段(源端口,目的端口,数据报的长度,长度和校验和,检验和是检测UDP用户数据报在传输中是否有错,有错就丢弃),首部字段只有八个字节,由四个字段组成,,每个字段的长度都是两个字节。

由于UDP是无连接的,所以不需要使用套接字来建立连接

UDP用户数据报校验和的计算有些特殊,他会封装一个12个字节的伪首部,而他只用于计算校验和,而不进行封装传输。

检验和的具体计算,和ip数据报的校验相识而又不同,ip数据报的检验和只检验ip数据报的首部,但UDP的检验和是把首部和数据部分一起都检验。

5.面向连接的TCP的特点:传输控制层协议TCP

  1. TCP是面向连接的运输层协议,应用进程的通信就好像打电话。
  2. 每一条tcp连接只能是两个端点即1对1
  3. TCP提供全双工通信,TCP允许通信双方在任何时候都能发送数据,TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据,应用进程把数据交给缓存以后就可以做自己的事情了
  4. 面向字节流,TCP中流的含义,是指流入到进程或从进程流出的字节序列。

面向字节流的含义就是,虽然应用进程交给TCP的是一次一个数据块,但TCP仅仅把它看作是一串无结构的字节流,发送方应用程序可能给TCP10个数据块,但是TCP可能只用四个数据块就把他发出去了,即把他看作无结构的字节流,但是接收方和发送方的字节流是完全一样的。

报文的长度:UDP发送报文的长度是由应用程序给出的,而应用程序传送到TCP缓存的数据块太长,TCP就会把他划分短一些再传送。如果太短,则等待积累。

TCP连接是端到端连接的,这个端的含义是套接字或插口=ip地址:端口.每一条TCP连接都被唯一的两个端点所确定,同时,同一个id地址可以有多个不同的TCP连接,同一个端口也可以出现在多个不同的tcp连接中。

6.可靠传输的工作原理:

我们知道ip只提供尽最大努力的服务,也就是说TCP下面的网络所提供的是不可靠的服务,那么想要可靠,TCP就必须采取适当的措施。通过确认和重传机制就可以在不可靠的网络上实现可靠通信,这种可靠的传输协议通常称为自动重传请求ARQ。意思是重传的请求是自动进行。接收方不需要请求发送方重传某个出错的分组,而是使用超时计时器来控制。停止等待协议的优点是简单,但是信道利用率太低,所以发送方不采用这种方式,而是采用流水线传输的方式,流水线传输就是发送方可以连续发送多个分组,不必发完一个分组就停顿下来等待对方的确认。使用流水线传输就要使用连续ARQ协议和滑动窗口协议。滑动窗口比较复杂,是TCP协议的精髓所在。

连续ARQ协议:

 

连续的ARQ协议规定,发送方每收到一个确认,就把滑动窗口向前滑动一个分组的位置,接收方采用的是累积确认的方式,也就是说接收方不必对收的分组逐个发送确认,而是收到几个分组后对按顺序到达的最后一个分组发送确认。这表示到这个分组为止的所有分组都已正确收到。

连续的ARQ有什么问题呢?比如发送方发送了前面5个分组,而中间的第三个分组丢失了,这时接收方只能对前面的两个分组发出确认,只好把后面的三个分组都在重传一次。如果通信线路的质量不好,可见连续ARQ协议会带来负面的影响。

7.TCP报文的首部格式

 TCP报文段首部的前20个字节是固定的,后面有4n字节是根据需要而增加的选项,所以TCP首部的最小长度是20个字节。

 

首部固定部分各字段意义如下:

1) 源端口和目的端口       各占2个字节,分别写入源端口和目的端口。

2) 序号              占4字节。序号范围是【0,2^32 - 1】,共2^32(即4294967296)个序号。序号增加到2^32-1后,下一个序号就又回到0。也就是说,序号使用mod 2^32运算。TCP是面向字节流的。在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在连接建立时设置。首部中的序号字段值则是指的是本报文段所发送的数据的第一个字节的序号。例如,一报文段的序号是301,而接待的数据共有100字节。这就表明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。显然,下一个报文段(如果还有的话)的数据序号应当从401开始,即下一个报文段的序号字段值应为401。这个字段的序号也叫“报文段序号”。

3) 确认号      占4字节,是期望收到对方下一个报文段的第一个数据字节的序号。例如,B正确收到了A发送过来的一个报文段,其序号字段值是501,而数据长度是200字节(序号501~700),这表明B正确收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701。注意,现在确认号不是501,也不是700,而是701。

       总之:若确认号为= N,则表明:到序号N-1为止的所有数据都已正确收到

4) 数据偏移         占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。由于首部中还有长度不确定的选项字段,因此数据偏移字段是必要的,但应注意,“数据偏移”的单位是32位字(即以4字节的字为计算单位)。由于4位二进制数能表示的最大十进制数字是15,因此数据偏移的最大值是60字节,这也是TCP首部的最大字节(即选项长度不能超过40字节)。

5) 保留          占6位,保留为今后使用,但目前应置为0 。

下面有6个控制位,用来说明本报文段的性质。

6) 紧急URG(URGent)        URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快发送(相当于高优先级的数据),而不要按原来的排队顺序来传送。例如,已经发送了很长的一个程序要在远地的主机上运行。但后来发现了一些问题,需要取消该程序的运行,因此用户从键盘发出中断命令。如果不使用紧急数据,那么这两个字符将存储在接收TCP的缓存末尾。只有在所有的数据被处理完毕后这两个字符才被交付接收方的应用进程。这样做就浪费了很多时间。

       当URG置为1时,发送应用进程就告诉发送方的TCP有紧急数据要传送。于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍然是普通数据。这时要与首部中紧急指针(Urgent Pointer)字段配合使用。

7) 确认ACK(ACKnowledgment)      仅当ACK = 1时确认号字段才有效,当ACK = 0时确认号无效。TCP规定,在连接建立后所有的传送的报文段都必须把ACK置为1

8) 推送 PSH(PuSH)   (尽快提交包给应用层) 当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。这时,发送方TCP把PSH置为1,并立即创建一个报文段发送出去。接收方TCP收到PSH=1的报文段,就尽快地(即“推送”向前)交付接收应用进程。而不用再等到整个缓存都填满了后再向上交付。

9) 复位RST(ReSeT)       当RST=1时,表名TCP连接中出现了严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。RST置为1还用来拒绝一个非法的报文段或拒绝打开一个连接。

10) 同步SYN(SYNchronization)       在连接建立时用来同步序号。当SYN=1ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1ACK=1,因此SYN置为1就表示这是一个连接请求或连接接受报文。

11) 终止FIN(FINis,意思是“完”“终”)          用来释放一个连接。当FIN=1时,表明此报文段的发送发的数据已发送完毕,并要求释放运输连接。

12) 窗口             占2字节。窗口值是【0,2^16-1】之间的整数。窗口指的是发送本报文段的一方的接受窗口(而不是自己的发送窗口)窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量(以字节为单位)。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。总之,窗口值作为接收方让发送方设置其发送窗口的依据。

      例如,发送了一个报文段,其确认号是701,窗口字段是1000.这就是告诉对方:“从701算起,我(即发送方报文段的一方)的接收缓存空间还可接受1000个字节数据(字节序号是701~1700),你在给我发数据时,必须考虑到这一点。”

      总之:窗口字段明确指出了现在允许对方发送的数据量。窗口值经常在动态变化。

13) 检验和       占2字节。检验和字段检验的范围包括首部和数据这两部分。和UDP用户数据报一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。伪首部的格式和UDP用户数据报的伪首部一样。但应把伪首部第4个字段中的17改为6(TCP的协议号是6);把第5字段中的UDP中的长度改为TCP长度。接收方收到此报文段后,仍要加上这个伪首部来计算检验和。若使用TPv6,则相应的伪首部也要改变。

14) 紧急指针            占2字节。紧急指针仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据) 。因此,在紧急指针指出了紧急数据的末尾在报文段中的位置。当所有紧急数据都处理完时,TCP就告诉应用程序恢复到正常操作。值得注意的是,即使窗口为0时也可以发送紧急数据。

15) 选项       长度可变,最长可达4字节。当没有使用“选项”时,TCP的首部长度是20字节。

       TCP最初只规定了一种选项,即最大报文段长度MSS(Maximum Segment Szie)。注意MSS这个名词含义。MSS是每一个TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个的TCP报文段。所以MSS并不是整个TCP报文段的最大长度,而是“TCP报文段长度减去TCP首部长度”。

       为什么要规定一个最大报文长度MSS呢?这并不是考虑接受方的接收缓存可能存放不下TCP报文段中的数据。实际上,MSS与接收窗口值没有关系。我们知道,TCP报文段的数据部分,至少要加上40字节的首部(TCP首部20字节和IP首部20字节,这里还没有考虑首部中的可选部分)才能组装成一个IP数据报。若选择较小的MSS长度,网络的利用率就降低。设想在极端情况下,当TCP报文段只含有1字节的数据时,在IP层传输的数据报的开销至少有40字节(包括TCP报文段的首部和IP数据报的首部)。这样,对网络的利用率就不会超过1/41。到了数据链路层还要加上一些开销。但反过来,若TCP报文段非常长,那么在IP层传输时就有可能要分解成多个短数据报片。在终点要把收到的各个短数据报片组成成原来的TCP报文段,当传输出错时还要进行重传,这些也都会使开销增大。

       因此,MSS应尽可能大些,只要在IP层传输时不需要分片就行。由于IP数据报所经历的路径是动态变化的,因此在这条路径上确定的不需要的分片的MSS,如果改走另一条路径就可能需要进行分片。因此最佳的MSS是很难确定的。在连接过程中,双方都把自己能够支持的MSS写入这一字段,以后就按照这个数值传输数据,两个传送方向可以有不同的MSS值。若主机未填写这一项,则MSS的默认值是536字节长。因此,所有在互联网上的主机都应该接受的报文段长度是536+20(固定首部长度)=556字节。

后来又增加了几个选项如窗口扩大选项、时间戳选项等。

      窗口扩大选项是为了扩大窗口。我们知道,TCP首部中窗口字段长度是16位,因此最大的窗口大小为64K字节。虽然这对早期的网络是足够用的,但对于包含卫星信道的网络,传播时延和宽带都很大,要获得高吞吐量需要更大的窗口大小。

       窗口扩大选项占3字节,其中有一个字节表示移位值S。新的窗口值等于TCP首部中的窗口位数从16增大到(16+S)。移位值允许使用的最大值是14,相当于窗口最大值增大到2^(16+14)-1=2^30-1。

       窗口扩大选项可以在双方初始建立TCP连接时进行协商。如果连接的某一端实现了窗口扩大,当它不再需要扩大其窗口时,可发送S=0选项,使窗口大小回到16。

时间戳选项占10字节,其中最主要的字段是时间戳字段(4字节)和时间戳回送回答字段(4字节)。时间戳选项有以下两个概念:

      第一、 用来计算往返时间RTT。发送方在发送报文段时把当前时钟的时间值放入时间戳字段,接收方在确认该报文段时把时间戳字段复制到时间戳回送回答字段。因此,发送方在收到确认报文后,可以准确地计算出RTT来。

       第二、 用于处理TCP序号超过2^32的情况,这又称为防止序号绕回PAWS。我们知道,TCP报文段的序号只有32位,而每增加2^32个序号就会重复使用原来用过的序号。当使用高速网络时,在一次TCP连接的数据传送中序号很可能被重复使用。例如,当使用1.5Mbit/s的速度发送报文段时,序号重复要6小时以上。但若用2.5Gbit/s的速率发送报文段,则不到14秒钟序号就会重复。为了使接收方能够把新的报文段和迟到很久的报文段区分开,则可以在报文段中加上这种时间戳。

8.TCP的可靠传输的实现:

   

 

以字节为单位的滑动窗口:

   TCP的滑动窗口是以字节为单位的,现假定A收到了B发来的确认报文段,其中窗口是20(字节)而确认号是31(这表明B期望收到的下一个序号是31,而序号30为止的数据已经收到了)。根据这两个数据,A就构造出自己的发送窗口:

  

我们先讨论发送方A的发送窗口。发送窗口表示:在没有收到B的确认的情况下,A可以连续把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。

   发送窗口里面的序号表示允许发送的序号。显然,窗口越大,发送方就可以在收到对方确认之前连续发送更多的数据,因而可能获得更高的传输效率。但接收方必须来得及处理这些收到的数据。接收方会把自己接收窗口的数值放在窗口字段中发送给对方,因此A发送窗口一定不能超过B接收窗口的数值,发送方发送窗口的大小还要受当时网络拥塞程度的制约。发送窗口后沿的后面部分表示已发送且已收到确认,这些数据显然不需要再保留了,而发送窗口的前沿前面部分的数据是不允许发送的,因为接受方都没有为这部分数据保留临时存放的缓存空间。

  发送窗口的位置由窗口的前沿后沿共同确定,发送窗口后沿的变化情况有两种可能,没有收到新确认就不动,收到新确认就前移,发送窗口后沿不可能向后移动。

  华东窗口正常情况下会不断的向前移动,但是当没有收到新确认,对方通知的窗口大小也没变,或收到新确认而对方通知的窗口缩小了,使得发送窗口前沿正好不动。

发送窗口前沿也有可能向后收缩。这发生在对方通知的窗口缩小了。但TCP的标准强烈不赞成这样做。因为很可能发送方在收到这个通知以前已经发送了窗口中的许多数据,现在又要收缩窗口,不让发送这些数据,这样就会产生一些错误。

 总结:

后沿位置有两种情况:

  • 后沿不动
    表示一直没收到确认信息。
  • 后沿向前移动
    表示收到了发送窗口内的连续确认信息。

注意:后沿窗口不可能向后移动,这是因为不可能撤销已经确认的信息

前沿位置有可能也有两种情况:

  • 向前移动
    正常收到确认信息,通知的窗口大小不变,或者变大。
    比如:收到2个字节的确认,即使通知的窗口大小不变,前沿也会向前移动2个字节。
  • 不动
    1,没有收到确认消息,对方通知的窗口大小也不变;
    2,收到确认消息,但是对方通知的窗口变小
    例如:收到2个字节的确认,通知窗口大小减少2个字节。这种情况下窗口大小刚好不变。
  • 向后收缩
    例如:收到2个字节的确认,但是对方的通知窗口大小减少3个字节。导致前沿位置向后收缩。TCP标准强烈不赞成这样做

 

要描述一个发送窗口的状态需要三个指针,P1,P2,P3,小于P1的是已发送并已收到确认的部分,而大于P3的是不允许发送的部分,

P3-P1=A的发送窗口

P2-P1=已发送但尚未收到确认的字节数

P3-p2=允许发送但当前尚未发送的字节数

 

再看一下B的接收窗口,B的接收窗口的大小是20个字节,在接收窗口的外面到三十号为止的数据是已经发送过确认的,并且已经交付给主机了的,因此B可以不再保留这些数据,接收窗口内的(31-50)是允许接收的,但是此时B只收到了32和33的数据,也就是说这些数据没有按顺序到达,因为序号为31的数据没有收到(也许丢失了,也许滞留在网络中的某处),这时,B只能对按序收到的数据中的最高序号给出确认,因此B发送的确认报文段中的确认号仍然是31,即期望收到的序号,而不能是32或33.

接着假定B收到了序号为31的数据,并把序号为31-33的数据交付给了主机,然后B删除了这些数据,接着把接收窗口向前移动了三个序号,然后给A发送确认其中窗口的值任然是20,但确认号是34。B还收到了37,38,40的数据,由于没有按顺序到达所以先暂时存在接收窗口中,A收到B的确认后,可以把发送窗口向前滑动3个序号,但指针P2不动,现在A的可用窗口增大了(42-53)。

A继续发送完序号42-53的数据后,指针p2向前移动和p3重合,发送窗口内的序号都已用完,但是还没有再收到确认,A的发送窗口已满,可用窗口已减小到0,所以必须停止发送,当然有可能发送窗口内的所有数据都已经正确发送,B也发送了确认,但是A没有收到这个确认,为了保证可靠的传输,A只能认为B没有收到这些数据,所以计时超时后A会重新发送这些数据,直到收到B的确认为止,如果A收到的确认号落在发送窗口内,那么A就可以使发送窗口继续向前滑动,并发送新的数据。

窗口和缓存的关系:

  发送方的应用进程把字节流写入tcp的发送缓存,接收方的应用进程从tcp的接收缓存中读取字节流。

  发送缓存

发送缓存用来暂时存放:

发送应用程序传送给发送方 TCP 准备发送的数据

TCP 已发送出但尚未收到确认的数据

发送窗口通常只是发送缓存的一部分,已被确认的数据应当从发送缓存中删除,因此发送缓存的后沿是和发送窗口的后沿重合的。

接收缓存

接收缓存用来暂时存放:

按序到达的、但尚未被接收应用程序读取的数据;

不按序到达的数据

如果分组被检测出有差错就丢弃,如果应用程序来不及读取收到的数据,接收缓存最终就会被填满,使接受窗口减小到0,反之能及时读取,接收窗口就可以增大。但最大也不能超过接收缓存的大小。

接下来思考几个问题:

1.窗口是由接收窗口设置的,那发送窗口和接受窗口在同一时刻是不是一样大?

  并不总是一样大,因为一是网络传送窗口值需要一定的时间,二是发送方可以根据网络拥塞的情况来减少自己发送窗口的值。

2.对不按序达到的数据该如何处理?

  可能会丢弃,可能会存起来,因为如果一味的丢弃对网络资源的利用不利(发送方会重传数据),所以Tcp通常对不按序达到的数据先临时存在接受窗口中,等字节流所缺少的字节收到后,再按序上交到应用程序。

3.tcp接收方的累积确认功能

  接收方要在适合的时间发送确认,不能太早,因为这样会增大网络的传输开销,也不能太晚(0.5秒),太晚会导致发送方不必要的重传。

 再次强调,TCP通信是全双工,每一方都有自己的发送和接收窗口。

 

4.超时重传的时间选择:

  这个时间选择是tcp最复杂的问题之一。为什么复杂呢?因为TCP的下层是互联网的环境,发送的报文段可能只经过一个高率的局域网,也可能经过多个低速率的网路,并且每个ip数据报所选择的路由还可能不同。这个时候超时时间太短会增大网络传输开销,太长会引起不必要的重传,这就是他的复杂之处。

TCP应对这种情况采取了自适应的算法,就是测出往返时间,以这个时间略大一点为计

时器的时间,TCP 每发送一个报文段,就对这个报文段设置一次计时器.只要计时器设置的重传时间到但还没有收到确认,就要重传这一报文段。TCP 保留了 RTT (报文往返时间)的一个加权平均往返时间 RTTS(这又称为平滑的往返时间),第一次测量到 RTT 样本时,RTTS 值就取为所测量到的 RTT 样本值.以后每测量到一个新的 RTT 样本,就按下式重新计算一次 RTTS.若α很接近于零,表示 RTT 值更新较慢若选择 α 接近于1,则表示 RTT 值更新较快

只要是重传就不采用其往返时间的样本,这样得出的加权平均往返时间和超时重传的时间就比较准确。

5.如果收的报文无差错只是未按序号怎么办?
     选择确认SACK是一种可行的方法,如果这些字节的序号都在接收窗口内,那么接收方先收下这些数据,但要把这些信息准确的告诉发送方,使发送方不要再重复发送这些已收到的数据。

  未完待续~~~~~~~~~~~~~~

 

参考博客:https://www.cnblogs.com/wodemeng/p/4583506.html

         https://www.cnblogs.com/newwy/p/3254029.html
         https://www.cnblogs.com/gaoyanqing/p/4823242.html

         https://www.cnblogs.com/zmlctt/p/3690998.html

 

 

 

 

 

 

 

 

 

 

 

  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时空恋旅人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值