关于TCP和UDP的一些问题记录

关于TCP和UDP的一些问题:

 1. tcp数据流与udp数据报?

  tcp是面向连接的字节流,TCP把应用程序看成是一连串的无结构的字节流,TCP有一个缓冲,应用发送太长可以分片发送,太短也可以积累足够多后再发送(mss控制分片)
客户端连续发送数据,只要服务端的这个函数的缓冲区足够大,会一次性接收过来,所以证明是无边界的。

  udp面向无连接的数据报的,类似快递包裹,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文,文太长,则IP层需要分片(mtu控制分片)
客户端连续发送数据,即使服务端的这个函数的缓冲区足够大,也只会一次一次的接收,发送多少次接收多少次,即客户端分几次发送过来,服务端就必须按几次接收
从而证明,这种UDP的通讯模式是有边界的。

问:
  发送100,200, tcp和udp使用recv1000来接收,分别接收的是多少? 100,200,300?
答:    
  tcp:300
  udp:可能100,也可能200,取决于哪个先到

2.  TCP中消息封装及粘包、不完整包处理

      如上1,可以知道TCP数据流会造成粘包,而UDP不会

     针对这个问题,一般有3种解决方案:

    (1)发送固定长度的消息。                 如:接收发送方发送固定的结构体,直接每次按照固定的长度读取

    (2)把消息的尺寸与消息一块发送。  如: 先定义一个固定长度的header,包含后续内容的长度,然后再收。

    (3)使用特殊标记来区分消息间隔。  如:http协议等,加个头尾<html></html>

3.  TCP三次握手和四次挥手

  1. 三次握手:

      一次:建立连接时,客户端发送syn包到服务器,等待服务器确认

      二次:服务器收到客户端的syn包,必须确认客户的SYN,即ack包。 于此同时自己也需要发送一个SYN包;总的就是sync+ack。

                                因为全双工,所以需要服务器给客户端再来一次sync,建立链接。

      三次:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK。  此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

        2. 四次挥手:

      一次: 客户端发出连接断开报文FIN,通知服务器要断开,等待服务器响应

      二次: 服务器收到FIN后,先会ACK报文,然后进入close_wait状态,半关闭状态,等待下一步,因为此时客户端可能没数据了,但是服务端可能有数据要发出去,客户端还是会响应的。

          此时客户端收到FIN-ACK后,也是会进入等待状态,半关闭状态,即客户端本身没啥数据发送,但是如果服务端有数据,还是要处理的。

                     三次: 服务端处理完最后的数据后,会发送FIN,等待客户端最后的确认

                     四次:  客户端收到FIN后,会再次确认FIN-ACK。 服务端接收此包后,立马进入close状态,而客户端此时可能还没有进入close状态,需经过最长报文段寿命后,再进入close状态。

          可以看出,服务端会优先于客户端断开。

4. tcp分片与udp分片?

  TCP会分段,不通过IP层来进行分片!
  MSS是TCP里的一个概念(首部的选项字段中)。MSS是TCP数据包每次能够传输的最大数据分段,TCP报文段的长度大于MSS时,要进行分段传输。TCP协议在建立连接的时候通常要协商双方的MSS值

  UDP不会分段,由IP层根据MTU来进行分片。

        MTU是链路层中的网络对数据帧的一个限制,一个IP数据报在以太网中传输,如果它的长度大于该MTU值,就要进行分片传输,使得每片数据报的长度小于MTU。

         分片传输的IP数据报不一定按序到达,但IP首部中的信息能让这些数据报片按序组装。IP数据报的分片与重组是在网络层进完成的。
         一般以太网MTU都为1500, 所以在以太网中, 往往TCP MSS为1460。

问:
  如果MTU是1500,使用UDP发送 2000,那么recvfrom(2000)是收到1500,还是2000? TCP呢?

答:
  UDP接收2000,数据分片由ip层处理了,放到udp还是一个完整的包。
  TCP也是2000,只要不超过缓冲区,分段由tcp协议层完成了。

5. TCP报文段发送时机的选择

TCP报文段发送时机主要有以下几种选择途径。
  1)TCP维持一个变量,它等于最大报文段长度MSS,只要缓存中存放的数据达到MSS字节就组装成一个TCP报文段发送出去。
  2)由发送方的应用程序指明要求发送报文段,即TCP支持的推送操作
  3)是发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段发送出去。

5. tcp流量控制

  所谓的流量控制就是让发送方的发送速率不要太快,让接收方来得及接受。
  tcp利用滑动窗口机制可以很方便的在连接上实现对发送方的流量控制。
  TCP的窗口单位是字节,不是报文段,发送方的发送窗口不能超过接收方给出的接收窗口的数值

假如设主机A向主机B发送数据。双方确定的窗口值是400,
接收方B进行了三次流量控制,第一次把窗口设置为rwind=300,第二次减小到rwind=100最后减到rwind=0,即不允许发送方再发送过数据了。
这种使发送方暂停发送的状态将持续到主机B重新发出一个新的窗口值为止。

假如,B向A发送了零窗口的报文段后不久,B的接收缓存又有了一些存储空间,于是B向A发送了rwind=400的报文段,然而这个报文段在传送中丢失 了。
A一直等待收到B发送的非零窗口的通知,而B也一直等待A发送的数据。这样就死锁了。
为了解决这种死锁状态,TCP为每个连接设有一个持续计时器。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器,
若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带1字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值

6. tcp拥塞控制

  如果网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,然而重传会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,
这就导致了恶性循环,最终形成“网络风暴” —— TCP的拥塞控制机制就是用于应对这种情况。

  拥塞的标志
    1.重传计时器超时
    2.接收到三个重复确认

  拥塞控制与流量控制的区别
    拥塞控制是防止过多的数据注入到网络中,可以使网络中的路由器或链路不致过载,是一个全局性的过程。
         流量控制是点对点通信量的控制,是一个端到端的问题,主要就是抑制发送端发送数据的速率,以便接收端来得及接收。

              拥塞控制主要是针对发送端来控制处理,而流量控制,是通过接收方发送滑动窗口的大小来限制

              拥塞控制在发送端定义了一个拥塞窗口(Congestion Window),字节为单位,在开始发送的时候,将拥塞窗口的大小与接收端ack的窗口大小做比较,取较小者作为发送数据量的上限。
             开始发送一个MSS


  拥塞控制有四个算法:
    1. 慢启动
      意思是刚刚加入网络的连接,一点点的发送,每接收到一个ack后,将cwnd成指数级增加,直到一个阈值(默认开始好像是16),开始进行拥塞避免
    2. 拥塞避免
      到达阈值后,cwnd就不再成指数级增加,而是线性的++,避免增长过快造成拥堵,一旦发现有重传,即进行快速重传
    3. 快速重传
      快速重传后,老版本,直接就阈值减半,cwnd又重新开始进行慢开始,新版本之后,采用的就是快速恢复

          快重传要求

        1.接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。
    快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期
    如:发送M1,M2,M3,M4,M5, 接收收到M1,M2丢了,再接受到M3,M4,M5的时候都会发出M2的重复确认,因为345是失序,正序是2才对。
        2. 由于不需要等待设置的重传计时器到期,能尽早重传未被确认的报文段,能提高整个网络的吞吐量

    4. 快速恢复(相比较慢启动,就是不再执行慢开始算法)
      将阈值减半,cwn等于阈值,然后再开启拥塞避免,慢慢的线性++
      优化:
       为什么使用快速恢复,不采用慢开始了,主要考虑:
       如果网络真的出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。
       所以此时不执行慢开始算法,而是将cwnd设置为ssthresh的大小,然后执行拥塞避免算法,迅速进入第二个阶段,直接跳过慢开始。
       采用快恢复算法时,慢开始只在TCP连接建立时和网络出现超时时才使用。

原文地址:https://www.cnblogs.com/leehm/p/13390504.html