网络协议之TCP

TCP协议

  • TCP协议段格式

网络协议之TCP_第1张图片

  • 4位TCP报头长度:4位表示的最大10进制数为15,15*32/8= 60字节 所以报头最大长度为60字节

  • 6位标志位:

    1. URG:紧急指针是否有效
    2. ACK:确认号是否有效
    3. PSH:提示接受端应用程序立即从TCP缓存区把数据读走
    4. RST:对方要求重新建立连接;携带RST标识的报文段称为复位报文段
    5. SYN:请求建立连接;携带SYN标识的称为同步报文段
    6. FIN:通知对方本端关闭,携带FIN为结束报文段
  • 16位校验和:发送端填充,CRC校验,接收端校验不通过,则认为数据有问题,校验和不光包含TCP首部,也包含TCP数据部分

  • 16位紧急指针:标识哪部分数据是紧急数据

  • TCP三次握手四次挥手

网络协议之TCP_第2张图片

  • 三次握手

    1. 调用socket,创建连接套接字
    2. 调用connect,向服务器发起连接请求
    3. connect发出SYN段并阻塞等待服务器应答(第一次握手)
    4. 服务端收到客户端的SYN后,会应答一个SYN-ACk段表示同意建立连接 (第二次握手)
    5. 客户端收到SYN-ACK后会从connect返回,同时应答一个ACK段
  • 四次挥手

    1. 客户端调用close,发出FIN段(第一次挥手)
    2. 服务端收到FIN段,会应答一个ACK,同时服务端read会返回0 (第二次挥手)
    3. read返回0后,服务端知道客户端关闭了连接,所以也会close关闭连接,此时发出一个FIN段(第三次挥手)
    4. 客户端收到FIN段,再返回一个ACK给服务端
  • 问题:

    1. 为啥需要第三次握手:

      需要第三次握手的原因是如果A向B发送连接请求报文段,由于网络原因滞留了,直到连接释放后才到达B,这个报文段是一个失效的请求报文段,B误以为收到了新的连接请求,于是就向A发出了确认报文段,同意建立连接,但是A并没有发出建立连接的请求,因此不会理会B的确认,但B认为新的连接已经建立了,就会白白创建connfd浪费资源

    2. 为啥需要四次挥手

      当服务端收到客户端发来的FIN段时,很可能不会立即调用close关闭socket,所以只能先发送一个ACK确认服务端已经收到,然后等服务端所有的报文全部发完,再调用close关闭socket并发送FIN段

    3. 为什么TIME_WAIT状态需要2MSL才能回到CLOSED状态

      客户端接收到服务端发送的FIN端后,会向服务端发送一个ACK段,如果发送的这个ACK段在网络传输的过程中丢失了,那么服务端没有收到ACK段,就会继续重复发送FIN段,所以客户端不能立即关闭,必须确认服务端接收到了ACK

    4. 如果建立了连接,客户端故障了

      TCP设有保活计时器,服务端每收到一次客户端请求都会重置这个计时器,时间通常是两小时,若两个小时还没收到客户端任何数据,服务端就会发送一个探测报文,以后每隔75秒发送一次,若连发10次没反应就关闭连接

  • 确认应答机制(ack)

    TCP是面向字节流传输,TCP将每个字节的数据都编号,即序列号,当发送数据时都会携带seq,如seq=1,同时接收端会有一个ack带有确认序号,表明收到了那些数据,下次从哪发送如:ack=1001;

  • 超时重传

    1. 主机A发送数据给主机B,由于网络状况,数据无法到达主机B,如果主机A在一段时间内没有收到B发来的确认应答,就会重发
    2. 主机A没有收到主机B的ACK,也可能是ACK丢了,因此主机B会收到很多重复数据,所以TCP会通过序列号来去重

    TCP会动态计算超时时间,超时以500ms为一个单位,每次判定超时重发的时间是500ms的整数倍

  • 滑动窗口

    1. 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。
    2. 收到第一个ACK,滑动窗口向后移
    3. 操作系统内核为了维护这个滑动窗口,需要开辟发送缓存区来记录当前还有哪些数据没有应答,确认应答的数据,才能从缓冲区删掉
    4. 窗口越大,则网络的吞吐量就越高

    丢包重传:

    1. 数据包递达,ACK丢了

      不影响,可以通过后续的ACK确认

    2. 数据包丢了

      当一段报文段丢失后, 发送端会一直收到服务端应答的丢失ACK的确认序号

      如果发送端连续三次收到同一序号,就会将丢失的数据包重发

      当接收端接收到正确的ACK后,再次返回的ACK应是丢失ACK+6 *(序列大小),其实之前发送的都已经收到了,被放在内核的接收缓冲区

  • 流量控制

    接收端处理数据的速度是有限的,当发送端发送数据过快导致接收区的缓冲区被装满,这个时候发送端继续发送就会发生丢包,继而引起重传等一系列连锁反应,因此通过窗口大小来控制发送端的发送速度,这种机制就叫做流量控制

    1. 接收端将自己可以接受的缓冲区大小 放入TCP首部的16位窗口大小字段,通过ACK段通知发送端
    2. 窗口大小越大,说明网络的吞吐量越高
    3. 接收端一旦发现缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端
    4. 发送端接收到这个窗口大小后,就会减缓发送速度
    5. 如果接收端缓冲区满了,就会将窗口置为0,这时发送端不会发送数据,但是要定期发送窗口探测数据,以便实时检测缓存区是否有空余
  • 拥塞控制

    在网络情况不明的情况下,贸然发送大量数据,将会是其更加拥堵, TCP引入慢启动,先发送少量的数据测试传输速度,再确定用多大速度传输数据

    1. 发送开始时定义拥塞窗口大小为1
    2. 每次收到一个ACK应答,拥塞窗口加1
    3. 每次发送数据包时 将拥塞窗口和接收端反馈的窗口大小做对比,取较小的值作为实际发送的窗口
    4. 当拥塞窗口大小小于阈值,将指数增长,否则线性增长
  • 延迟应答

    如果接收数据的主机立即返回ACK应答,返回的窗口可能较小,所以需要延迟,是窗口大小变大

    数量限制: 每隔N个包应答一次

    时间限制: 超过最大延迟时间就应答一次

  • 捎带应答

    客户端向服务端发送数据后,服务端也发送数据时,ACK就可以和数据包一起回传给客户端

  • 面向字节流

    • 调用send时,数据会先写入发送缓冲区中
    • 如果发送的字节数太长,会被拆分成多个TCP数据包
    • 如果发送的字节数太短,就会现在缓冲区里等待,等待缓冲区长度差不多,或者其他合适的时机发出去
    • 接收数据时,数据也是从网卡驱动程序到达内核的接收缓冲区
    • 然后应用程序可以调用read从接收缓冲区拿数据
    • 另一方,TCP的连接,既有发送缓存区,又有接收缓冲区,那么对于这一个连接,既可以读数据,也可以写数据

发出去

  • 接收数据时,数据也是从网卡驱动程序到达内核的接收缓冲区
  • 然后应用程序可以调用read从接收缓冲区拿数据
  • 另一方,TCP的连接,既有发送缓存区,又有接收缓冲区,那么对于这一个连接,既可以读数据,也可以写数据

你可能感兴趣的:(网络,网络)