TCP

作者: 潘雪雯 | 来源:发表于2020-06-12 16:40 被阅读0次

传输控制协议 TCP(Transmission Control Protocol)

  • 特点
    是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)。

  • 首部

    image.png
    选项: 0~40字节
  • TCP校验和的实现
    TCP校验和由发送端计算,接收端验证。目的是为了发现TCP首部和数据在发送端到接收端之间发生的任何改动。TCP校验和覆盖TCP首部和TCP数据,校验和是必须的,并要加上12字节的伪首部(数据从IP数据报头获取,目的是让TCP检查数据是否已正确到达目的地)。
    首先,把伪首部、TCP报头、TCP数据分为16位的字,如果总长度为奇数个字节,则在最后增添一个位都为0的字节。把TCP报头中的校验和字段置为0
    然后,用反码相加法累加所有的16位字(进位也要累加)
    最后,对计算结果取反,作为TCP的校验和

  • 连接管理
    三次握手和四次挥手的原理

  1. 三次握手建立
    在socket编程中,客户端执行connect()操作即可触发三次握手
    image.png
  • 第一步:客户机的TCP首先向服务器的 TCP 发送一个连接请求报文段。这个特殊的报文段中不含应用层数据,其首部中的 SYN 标志位被置为1.另外,客户机会随机选择一个起始序号 seq=x (连接请求报文不携带数据,但要消耗掉一个序号)。然后客户端进入 SYN-SENT 状态,等待服务器的确认
  • 第二步:服务器的 TCP 收到连接请求报文后,如同意建立连接,就向客户机发回确认,并为该 TCP 连接分配 TCP 缓存和变量。在确认报文段中,SYN 和 ACK 位都被置为 1 ,确认号字段ack的值为 x+1,并且服务器随机产生起始序号 seq=y (确认报文不携带数据,但也要消耗掉一个序号)。确认报文段同样不包含应用层数据。
  • 第三步:当客户机收到确认报文段后,还要向服务器给出确认,并且也要给该连接分配缓存和变量。这个报文段的 ACK 标志为被置 1,序号字段seq为 x+1,确认号字段 ack=y+1。该报文段可以携带数据,如果不携带数据则不消耗序号

为什么 "三次握手" 而不是 "两次握手" 建立连接:
防止两次握手情况下已失效的连接请求报文突然又传送到服务器而产生错误。
三次握手的目的:确认对方的接收与发送能力是否正常。
考虑客户A向服务器B发出TCP连接请求:
第一个连接请求报文在网络的某个结点长时间滞留,A超时后认为报文丢失,于是再重传一次连接请求,B收到后建立连接。
数据传输完毕后双方断开连接。而此时,前一个滞留在网络中的连接请求到达服务器B,而B认为A又发来连接请求,
此时若使用“三次握手”,则B向A返回确认报文段,由于是一个失效的请求,因此A 不予理睬,建立连接失败。
若采用“两次握手”,则这种情况下B认为传输连接已经建立,并一直等待A传输数据,而A此时并没有连接请求,因此不予理睬,这样就白白浪费B的资源。
半连接: 服务器第一次收到客户端的SYN之后,就会处于SYN_RCVD状态,此时双方还没有完全建立连接,服务器把此种状态下请求连接放在一个队列中,这种队列称之为半连接队列
全连接: 已完成三次握手,建立起连接的就会放在全连接队列中。如果队列满就可能出现丢包现象。
三次握手是否可以携带数据: 第一次、第二次握手不可以携带数据。因为第一次握手若携带数据,会让服务器更加容易受到SYN攻击。第三次的话,客户端已经处于ESTABLISHED状态,对于客户端来说,已经建立起连接,并知道服务器的接收,发送能力正常,所以能携带数据。
SYN攻击:
服务器的资源分配是在第二次握手时分配,客户端资源是在完成三次握手时分配。,所以服务器容易受到SYN洪泛攻击。SYN攻击就是Client短时间内伪造大量不存在的IP地址,并向Server不断发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN攻击是一种典型的Dos/DDos攻击。

解决策略:
SYN cookies技术当服务器接受到 SYN 报文段时,不直接为该 TCP 分配资源,而只是打开一个半开的套接字。接着会使用 SYN 报文段的源 Id,目的 Id,端口号以及只有服务器自己知道的一个秘密函数生成一个 cookie,并把 cookie 作为序列号响应给客户端。
如果客户端是正常建立连接,将会返回一个确认字段为 cookie + 1 的报文段。接下来服务器会根据确认报文的源 Id,目的 Id,端口号以及秘密函数计算出一个结果,如果结果的值 + 1 等于确认字段的值,则证明是刚刚请求连接的客户端,这时候才为该 TCP 分配资源,这样一来就不会为恶意攻击的 SYN 报文段分配资源空间,避免了攻击。
过滤网关防护
增加最大半连接数
缩短超时(SYN Timeout)时间

  1. 四次挥手
    在socket编程中,任何一方执行close()操作即可产生挥手操作
    四次挥手释放TCP连接
  • 第一步:客户端打算关闭连接,就向其 TCP 发送一个连接释放报文段,并停止再发送数据,主动关闭 TCP 连接,该报文的 FIN 标志位被置为 1,seq=u,它等于前面已传送过的数据的最够一个字节的序号加 1 (FIN 报文段即使不携带数据,也要消耗掉一个序号)。TCP 是全双工的,即可以想象成是一条 TCP 连接上的两条数据通路。当发送 FIN 报文时,发送 FIN 的一端就不能再发送数据,也就是关闭了其中一条数据通路,但对方还可以发送数据
  • 第二步:服务器收到连接释放报文段后即发出确认,确认号是 ack=u+1,而这个报文段自己的序号是 v,等于它前面已传送过的数据的最后一个字节的序号加 1。此时,从客户机到服务器这个方向的连接就释放了,TCP 连接处于半关闭状态。但服务器若发送数据,客户机仍要接收,即从服务器到客户机这个方向的连接并未关闭
  • 第三步:若服务器已经没有要向客户机发送的数据,就通知 TCP 释放连接,此时其发出 FIN=1 的连接释放报文段
  • 第四步:客户机收到连接释放报文段后,必须发出确认。在确认报文段中,ACK 字段被置为 1,确认号 ack=w+1,序号 seq=u+1。此时 TCP 连接还没有释放掉,必须等待时间计时器设置的时间 2MSL 后,A 才进入到连接关闭状态。
    常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。
    TIME_WAIT 状态存在的必要性
  1. 客户端最后向服务器发送的确认 ACK 是有可能丢失的(可靠的关闭TCP连接。)
    为了保证 客户端发送的最后一个确认报文段能够到达服务器端。如果 客户端 不等待 2MSL,在此期间若 客户端返回的最后确认报文段丢失,则 服务器不能进入正常关闭状态,而 客户端此时已经关闭,也不可能再重传。
  2. 避免新旧连接混杂(.防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失))
    客户端在发送完最后一个确认报文段后,再经过 2MSL 可保证本连接持续的时间内所产生的所有报文段从网络中消失。
    假设没有time-wait 限制,因某些原因我们先关闭这条TCP连接,然后很快又以相同的<源ip,源port,目的ip,目的port> 建立一个新的TCP连接,然后发送数据,设想此时前一个连接在网络中滞留的数据报现在到达接收方,会被当做正常数据接收并上传到应用层,而这些旧数据不应该被接收。从而引起数据错乱而导致各种无法预知诡异错误
    服务器保持大量的time-wait 状态如何避免
  3. 让服务器能够快速回收和重用那些TIME_WAIT的资源。
#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭  
net.ipv4.tcp_tw_reuse = 1  
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭  
net.ipv4.tcp_tw_recycle = 1  

这篇文章讲得不错

  1. SO_REUSEADDR 套接字(so_resueaddr)
    首先服务器可以设置 SO_REUSEADDR 套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场景就是,如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态。
    服务器出现了大量 CLOSE_WAIT 状态如何解决
    说明在对方关闭连接之后服务器程序自己没有进一步发出ack信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。
    解决方法:检查代码,特别是释放资源的代码,或者是处理请求的线程配置。
    流量控制和拥塞控制
    流量控制和拥塞控制2

TCP拥塞控制

发送方根据自己的网络拥塞程度设置cwnd(拥塞窗口)的值来限制发送速率

  • 方法
    ssthtresh是慢开始门限值
  1. 慢开始算法
    cwnd<ssthresh,每收到一个对新报文段的确认后,将cwnd加1
  • 拥塞避免算法
    cwnd>ssthresh时,每经过一个往返时延RTT,cwnd就增加一个
  • 快重传
    当收到连续的三个重复ACK,直接重传对方期待的报文
  • 快恢复
    当收到三个连续的冗余ACK(即重复确认),执行“乘法减少”算法,令ssthresh=cwnd=cwnd/2


    image.png

TCP流量控制

TCP提供一种基于滑动窗口协议的流量控制机制,接收方根据自己接收缓存的大小,动态调整发送方的发送窗口大小。
滑动窗口的基本原理:
由接收方控制发送方发送数据的速率。
停止-等待协议: 发送窗口大小 =1 ,接收窗口大小 = 1.保证有序接收
后退N帧协议: 发送窗口大小>1,接收窗口大小 =1.保证有序接收
选择重传协议: 发送窗口大小>1,接收窗口大小>1.
#######滑动窗口、窗口、拥塞窗口的区分?
滑动窗口:批量发送报文的大小,提高发送报文的效率
拥塞窗口:当前网络可能造成拥堵的一个上限值/阈值
窗口:对象能接受的当前的最大的报文值
滑动窗口 = min[窗口,拥塞窗口]

相关文章

  • TCP那些事儿

    目录: TCP是什么TCP报文结构TCP连接过程TCP状态转移TCP流量控制 —— 滑动窗口TCP拥塞控制TCP可...

  • 计算机网络

    一、tcp/http 1、TCP首部。 IP数据报(IP首部+TCP报文段(TCP首部+TCP数据)) TCP首部...

  • TCP协议三次握手和四次挥手

    TCP协议 TCP/IP协议栈 由上图可知,TCP/IP协议栈包含很多的协议。 二. 什么是TCP TCP是TCP...

  • 15分钟TCP

    TCP协议详解 介绍TCP协议之前,先区分一下TCP协议,和TCP/IP体系结构。TCP协议是TCP/IP协议体系...

  • TCP 与 UDP

    TCP 与 UDP(主要说TCP)TCP/UDP端口号TCP/UDP端口号TCP连接的建立TCP连接的建立发送se...

  • 四 . TCP 编程

    什么是 TCP 编程 TCP 编程是建立在 TCP 协议上的 Socket 编程 什么是 TCP 协议 TCP (...

  • TCP HTTPS专题

    TCP HTTPS专题 TCP协议 TCP/IP协议分层 TCP/IP 协议族里重要的一点就是分层。 TCP/IP...

  • 浅谈 TCP

    这篇文章介绍 TCP 理论,主要分为「TCP 连接,TCP 优化,TCP 重连」三个方面。看《TCP/IP 详解》...

  • 传输层

    ICMP UDP TCP TCP的三次握手 TCP四次挥手 TCP状态机Tcp_status_map.jpg

  • TCP/IP

    引用 一文搞懂TCP与UDP的区别 TCP/UDP协议详解... TCP基础特性* TCP 1、 TCP特性: T...

网友评论

      本文标题:TCP

      本文链接:https://www.haomeiwen.com/subject/lybgtktx.html