TCP/UDP

一、TCP包头的格式

TCP包头
  • 首先是16位的源端口号和16位的目的端口号。用来告诉操作系统,这是哪个进程的包。
  • 然后是32位的序号,解决包的乱序问题。
  • 然后是32位的确认序号,防止在网络传输过程中包的丢失。
  • 然后接下来有一些状态位,例如SYN,表示发起一个链接;ACK,表示回复;RST,表示重新连接;FIN,表示结束等。因为TCP是面向连接的,所以这些状态位会引起双端状态的变更。
  • 接下来还有占16位的窗口大小,用来做流量控制拥塞控制,表明当前自己的处理能力和控制发送速度。

二、TCP的三次握手

  • TCP的三次握手发生在TCP连接建立时,
  • 第一次握手时,客户端将SYN状态位设置为1,随机产生一个初始序号x发送给服务端,进入SYN_SENT状态。
  • 第二次握手时,服务端在收到客户端发来的SYN=1的包后,就返回一个SYN、ACK状态位都为1的包,序号随机初始化为y,确认序号为收到的包的序号加1,也就是x+1,然后服务端进入SYN_RCVD状态。
  • 第三次握手时,客户端收到服务端发来的确认包,检查确认序号、ACK状态位等信息是否准确,如果正确,就返回一个ACK状态位为1,序号为x+1的确认包,发给服务器,然后进入ESTABLISHED状态;服务器收到这个包后,检查无误,则也进入ESTABLISHED状态。
  • 这样就完成了三次握手。


    TCP三次握手

三、为什么是三次握手,而不是两次或四次

如果是两次握手:

  • 假如。当A发送给B一个连接请求包,如果这个包迷路了,或者堵塞了,没有到达B,或者晚到B,则A可能会再次发送给B多个连接请求包。
  • 当B收到了连接请求包,表示同意连接,会发送应答包给A。完成了通信,结束了连接后,这时,A原来发送的连接请求包可能又到达了B。
  • B以为是A新发来的请求,所以会建立连接,这时B给A的应答包如果在网络中丢失了,就会造成A不知道B有这个连接,则这个连接会一直存在,浪费系统的资源。

为什么不是四次?

  • 因为三次就能让服务端知道他的应答包客户端收到了,如果使用4次,就冗余。

四、为什么序号不能都从1开始呢?

  • 因为网络中可能还会存在上一次连接中没有达到的包,如果序号从1开始,则上一次包的数据的序号可能会与本次连接的冲突,造成错误。
  • 所以序号需要随机产生,且在包的生存时间内不能重复。

五、TCP的四次挥手

  • TCP四次挥手发生在TCP连接断开时,
  • 第一次挥手假设是由客户端发起,则客户端会发送一个FIN=1的包,然后进入FIN_WAIT_1的状态。
  • 第二次挥手时,是服务端收到一个FIN=1的包,则发送一个ACK=1的确认包,进入CLOSED_WAIT状态;客户端收到这个包后,就进入FIN_WAIT_2状态。
  • 第三次挥手时,是服务端发送/处理完了最后的数据,向客户端发送一个FIN、ACK状态位为1的包,进入LAST_ACK状态。
  • 第四次挥手时,是客户端收到了服务端的FIN、ACK为1的包时,就发送一个ACK=1的包,进入TIME_WAIT状态,在等待两个最大报文生存时间后,就进入CLOSED状态;服务端收到这个ACK包时,也就进入CLOSED状态。

六、在客户端是FIN_WAIT_2状态时,如果服务器宕机,客户端此连接会怎样

  • 在linux里面,可设置一个超时参数,使其超时后自动关闭连接。

七、等待TIME_WAIT时间的意义

  • 在第四次挥手时,发送的确认包可能会在路上丢失,如果没有这个等待时间,客户端直接关闭的话,就会造成服务端的连接不能正常关闭。
  • 在有了这个等待时间后,如果第四次挥手的确认包丢失,则客户端可以等到服务端重发的第三次挥手的包,从而正确的关闭连接。

八、等待时间为什么设置为2MSL

  • MSL表示最大的报文生存时间,超过这个时间,仍在网络上的报文,会被抛弃。
  • 所以2MSL可以大概的表示此连接中所有的报文在网络中都不存在了。

九、过了2MSL,服务端还是没有收到它FIN的ACK,怎么办?

  • 这个时候,客户端在2MSL后,已经关闭了连接,收到服务端发来的FIN,会发送一个RST,服务端就会知道,客户端已经关闭了连接。

十、TCP为什么是可靠的?

  • TCP每个包都有一个序号,保证包的有序性。
  • TCP对每个收到的包都作出应答,保证包不丢失。用的是累计应答的方式,表示这个序号前的所有包都收到了。
  • TCP有重传机制,对每一个发出去的包都设置了一个定时器,如果超过了一定的时间,就重新发送这个包。这个时间必须大于往返时间RTT,否则会引起不必要的重传,但是也不能太大,不然会导致访问变慢。所以采用的是对当前网络进行数据包往返时间采样的方法,计算出一个平均值。当一个数据包重传两次时,表示当前的网络环境较差,TCP的策略是,重传时间间隔加倍,减少频繁的发送。
  • TCP还拥有一个快速重传机制,当接收方收到的包的序号大于所期望的包的序号时,会继续发送冗余ACK,比如说收到了6、8序号的两个包,7没来,就发送6的ACK,接下来,后续收到的包,都发送6的ACK。当发送方收到3个重复的ACK时,就不用等待超时,会马上重发。
  • TCP还会对数据包进行校验。

十一、TCP如何流量控制

  • TCP包中,会携带16位的窗口大小数据,表示自己接下来还能接收多少个包。
  • 假设接收方的应用一直不读取缓存里的数据,则窗口的大小会越来越小,直至为0。
  • 如果这样,发送方就会定时发送窗口探测包,查看是否有机会调整窗口的大小。

十二、TCP拥塞问题

  • 拥塞问题也是通过窗口大小来控制的。
  • 流量控制中的窗口,是怕发送方把接收方的缓存塞满,而拥塞窗口则是怕把网络塞满,因为网络中的设备其缓存大小都是有限的,如果网络中的包过多,占满了设备的缓存,则后续到达的包,就会被丢弃。如果网络设备的处理能力不行,则在设备缓存中保存的包,会超时重传。
  • 所以TCP拥塞控制就是在不堵塞、不丢包的情况下,尽量发挥带宽,避免包丢失和超时重传。
  • 在TCP的拥塞控制中,一开始是不知道网络的拥塞情况的,所以要慢开始,一开始的窗口大小设为1,所以只能发送一个包。当收到这个发送包的ACK时,窗口大小加1,在后续中,每收到一个确认包,窗口大小就加1。呈指数增长。
  • 当窗口大小到达设定的阈值时,就变为线性增长,当窗口的所有包都收到确认,窗口大小才加1。
  • 这时,如果出现了网络拥塞,比如说丢包了,需要超时重传,则将窗口大小的阈值变成现在窗口大小的一半,窗口大小设为1,重新开始慢启动。
  • 如果是快速重传,TCP会认为这时,网络只是部分丢包,情况不严重,所以窗口大小仅变为原来的一半,窗口大小的阈值也为原来的一半。继续线性增长。

十三、TCP和UDP的区别

  • TCP是有序、有确认机制、有状态的可靠连接协议;UDP是无序、不需要确认、没有状态的不可靠的协议。
  • TCP是面向字节流的,而UDP是面向报文的。
    面向流指的是没有保护消息边界,如果发送端连续发送消息,则接收端有可能在一次接收动作中,会接收两个或更多数据包。
    例如,我们连续发送三个数据包,大小分别是2k,4k,8k这三个数据包,都已经到达了接收端的网络堆栈(就是网络协议栈)中,如果使用UDP协议,不管我们使用多大的接收缓冲区去接收数据,我们必须有三次接收动作,才能够把所有的数据包接收完。而使用TCP协议,我们只要把接收的缓冲区大小设置在14k以上,我们就能够一次把所有的数据包接收下来,只需要有一次接收动作。
    面向流的传输,可以减少发送包的数量,从而减少TCP机制造成的额外开销。
  • TCP有拥塞控制,而UDP没有。
  • TCP的首部(20 字节)开销比UDP的(8字节)大。

十四、UDP包头的格式

  • 主要是有16位的源端口号和16位的目的端口号。

十五、UDP的特点

  • 包头的格式简单,只有源端口号和目的端口号
  • UDP是无连接的,其端口号可以同时给多个人传输数据,也可以接收任何人的数据,意思是可以多对多。
  • UDP没有拥塞控制,不管丢不丢包,都会发送。

十六、UDP的使用场景

  • 在网络环境比较好的内网或对于丢包不敏感的应用,可以使用UDP,比如说是DHCP,就是基于UDP的。
  • 对于不需要一对一沟通、建立连接,可以广播的应用。
  • 需要处理速度快、时延小,容许少量丢包的应用。

你可能感兴趣的:(TCP/UDP)