计算机网络之TCP详解

前言:了解基本术语

  • MSL(Maximum segment lifetime):报文最大生存时间。它是任何TCP报文在网络上存在的最长时间,超过这个时间报文将被丢弃。实际应用中常用的设置是30秒,1分钟和2分钟。TCP四次挥手时,需要在TIME-WAIT状态等待2MSL的时间,可以保证本次连接产生的所有报文段都从网络中消失。
  • TTL(Time to live):IP数据报在网络中可以存活的总跳数,称为“生存时间”,但并不是一个真正的时间。该域由源主机设置初始值,每经过一个路由器,跳数减1,如果减至0,则丢弃该数据包,同时发送ICMP报文通知源主机。取值范围1-255,如果设置的TTL 值小于传输过程中需要经过的路由器数量,则该数据包在传输中就会被丢弃。
  • RTT(Round trip time):客户端到服务端往返所花时间。RTT受网络传输拥塞的变化而变化,由TCP动态地估算。

一、TCP的三次握手和四次挥手

1. TCP的标志位

  • SYN
    发送/同步标志,用来建立连接,和ACK标志位搭配使用。A请求与B建立连接时,SYN=1,ACK=0;B确认与A建立连接时,SYN=1,ACK=1。
  • ACK
    确认标志,表示确认收到请求。
  • PSH
    表示推送操作,就是指数据包到达接收端以后,不对其进行队列处理,而是尽可能的将数据交给应用程序处理。
  • FIN
    结束标志,表示关闭一个TCP连接。
  • RST
    重置复位标志,用于复位对应的TCP连接。
  • URG
    紧急标志,用于保证TCP连接不被中断,并且督促中间层设备尽快处理。

2. TCP的序列号和确认号

2.0 前言:作用

序列号和确认号是TCP实现可靠传输的依赖。TCP使用序列号来记录发送数据包的顺序。对发送方而言,TCP传送一个数据包后,只有在指定时间里收到这个包的确认信息,才会将其从队列中删除,否则会重新发送该数据包。对接收方而言,通过数据分段中的序列号可以保证数据能够按照正常的顺序进行重组。
注意:这里我们说的是发送方和接收方,而不是客户端和服务端。因为并不是客户端就一定是发送方,服务端就一定是接收方。发送方和接收方的角色由谁来承担,主要取决于在当前的这个数据传输中的作用。

2.1 序列号(seq)

  • 当SYN标志位为1时,seq表示当前连接的初始序列号(isn);当SYN标志位为0时,seq表示当前报文字段中第一个字节的序列号。
  • 序列号的规则
    1. 握手阶段,SYN包没有传送数据,但会消耗一个序列号,建立连接后的序列号会从isn+1开始。
    2. 挥手阶段,FIN/ACK包没有传送数据,但会消耗一个序列号。
    3. 数据传输阶段,① 发送方发送的序列号=当前发送方发送的第一个报文段的序列号+已发送的字节数;② 如果发送方发送的报文段不携带数据,则不会消耗序列号,下一个报文段还是用相同的序列号发送; ③ 通常,接收方给发送方发送的确认号,就是发送方下一个报文段的序列号。

2.2 确认号(ack)

  • ACK标志位置1时才有效,表示接收方期待的下一个报文段的序列号。

3. 三次握手过程

3.1 详细流程叙述

在这里插入图片描述

  • 第一次握手
    1. 操作:客户端请求建立连接,向服务端发送一个同步包(SYN=1),同时选择一个随机数seq = x作为初始序列号。
    2. 状态:握手之前,客户端处于closed*(关闭)状态,表示连接尚未建立,服务端处于LISTEN(收听)状态,表示监听来自远程应用的TCP连接请求。握手之后,客户端处于SYN_SENT(同步已发送)状态,表示等待远端的确认。
    3. 注意:此时客户端作为发送方,发送seq。
  • 第二次握手
    1. 操作:服务端收到连接请求报文后,如果同意建立连接,则向客户端发送同步确认包(SYN=1,ACK=1),确认号为ack = x + 1,同时选择一个随机数seq = y作为初始序列号。
    2. 状态:握手之后,服务端处于SYN_RECV(同步已收到)状态,表明收到了连接请求并发送了确认报文,等待最终的确认。
    3. 注意:此时的服务端作为接收方发送ack,作为发送方发送seq。
  • 第三次握手
    1. 客户端收到服务端的确认后,向服务端发送一个确认包(ACK=1),确认号为ack = y + 1,序列号为seq = x + 1
    2. 状态:握手之后,服务端和客户端都处于ESTABLISHED(建立连接)状态,表明连接建立成功。
    3. 注意:此时客户端作为接收方发送ack,作为发送方发送seq。

3.2 大话三次握手

  1. 第一次握手:服务端确认“服务端收、客户端发”报文功能正常。
  2. 第二次握手:客户端确认“客户端收、客户端发、服务端收、服务端发”报文功能正常,客户端认为连接已建立。
  3. 第三次握手:服务端确认“服务端发、客户端收”报文功能正常,此时双方均建立连接,可以正常通信。
  • 从上面的叙述,也就不难看出为什么不能是两次握手或者四次握手。显然,两次握手不能确保成功建立连接,四次握手会造成额外资源的浪费。

3.3 SYN攻击及防范

  1. 什么是SYN攻击
  • 概念:SYN攻击属于DOS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。
  • 原理:
    1. 在三次握手过程中,服务器发送SYN/ACK包(第二个包)之后、收到客户端的ACK包(第三个包)之前的TCP连接称为半连接(half-open connect),此时服务器处于SYN_RECV(等待客户端响应)状态。如果接收到客户端的ACK,则TCP连接成功,如果未接受到,则会不断重发请求直至成功。
    2. SYN攻击的攻击者在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复SYN/ACK包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时。
    3. 这些伪造的SYN包将长时间占用未连接队列,影响了正常的SYN,导致目标系统运行缓慢、网络堵塞甚至系统瘫痪。
  1. 检测与防范
  • 检测:当在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。
  • 防范:主要有两大类,一类是通过防火墙、路由器等过滤网关防护,另一类是通过加固TCP/IP协议栈防范,如增加最大半连接数,缩短超时时间。但SYN攻击不能完全被阻止,除非将TCP协议重新设计,否则只能尽可能的减轻SYN攻击的危害。

4. 四次挥手过程

4.1 详细流程叙述

在这里插入图片描述

  • 第一次挥手
    1. 操作:客户端向服务端发送连接释放包(FIN=1),主动关闭连接,同时等待服务端的确认。发送序列号seq = m,这个序列号是客户端上次发送报文的最后一个字节的序号加1。发送确认号ack = n,表明对上次请求的回应。
    2. 状态:挥手前,服务端和客户端都处于ESTABLISTHED(建立连接)状态;挥手后,客户端处于FIN_WAIT_1(终止等待1)状态,表示发送了连接终止请求等待确认。
    3. 注意:客户端作为发送方发送seq,作为接收方发送ack。
  • 第二次挥手
    1. 操作:服务端收到连接释放报文后,立即发出确认包(ACK=1),序列号seq = n,确认号ack = m + 1。
    2. 状态:挥手后,服务端处于CLOSE_WAIT(关闭等待)状态。当客户端接收到确认信息后,处于FIN_WAIT_2(等待状态2),表示已经收到了远程的确认,等待远程TCP发送终止请求。
    3. 注意:服务端作为发送方发送seq,作为接收方发送ack。
  • 第三次挥手
    1. 操作:服务端向客户端发送连接释放包(FIN=1,ACK=1),主动关闭连接,同时等待A的确认。序列号为seq = p,并再次发送确认号ack = m + 1。
    2. 状态:挥手后,服务端处于LAST_ACK(最后确认)状态,表明等待发送的连接终止请求的确认。
    3. 注意:服务端作为发送方发送seq。
  • 第四次挥手
    1. 操作:客户端收到服务端的连接释放报文后,立即发出确认包(ACK=1),序列号seq = m+ 1,确认号为ack = p + 1。
    2. 状态:挥手后,客户端处于TIME_WAIT(时间等待)状态,表明等待足够的时间,以确保远程TCP收到其连接终止请求的确认;当服务端收到确认信息后,处于CLOSED(连接断开状态);经过2MSL后,客户端也处于CLOSED(连接断开状态)。
    3. 注意:客户端作为发送方发送seq,作为接收方发送ack。

4.2 大话四次挥手

1.为什么需要四次挥手

答:因为 TCP 是全双工的,一方关闭连接后,另一方还可以继续发送数据。所以四次挥手,将断开连接分成两个独立的过程。

2.为什么客户端最后要等待2MSL

  • 确保 ACK 报文能够到达服务端,从而使服务端正常关闭连接
    在四次挥手时,只要发送方发出了第四次挥手的报文之后,发送方就进入了等待状态,这时最后一个报文其实是并没有确认的,这个等待计时器主要是为了确保发送方发送的第四次挥手ACK报文可以到达接收方。MSL是报文在网络中最长可以存活的时间,在2MSL时间里,如果第四次挥手ACK报文没到达服务端,接收方会重新发送第三次挥手的报文给客户端,客户端收到之后,就知道之前第四次挥手的 ACK 报文丢失了,然后再次发送 ACK 报文。确保正确地结束这次连接。
  • 防止已失效的连接请求报文段出现在之后的连接中
    因为最后一个报文都已经等待了2MSL时间,所以对于其他报文,肯定也超过2MSL的时间,此时所有报文就保证了都是过期的报文。

5. 突发情况

如果已经建立了连接,但是客户端出现故障了怎么办

答:通过定时器 + 超时重试机制,尝试获取确认,直到最后会自动断开连接。具体而言,TCP设有一个保活计时器。服务器每收到一次客户端的数据,都会重新复位这个计时器,时间通常是设置为2小时。若2小时还没有收到客户端的任何数据,服务器就开始重试,每隔75秒发送一个探测报文段,若一连发送10个探测报文后客户端依然没有回应,那么服务器就认为连接已经断开了。

二、TCP的流量控制和拥塞控制

1. 流量控制

1.1 目的

  • 流量控制的目的是控制发送端的发送速度,使其按照接收端的数据处理速度来发送数据,避免接收端处理不过来,产生网络拥塞或丢包。

1.2 策略

  • TCP实现流量控制的关键是滑动窗口(Sliding Window)。发送端和接收端均有一个滑动窗口,对应一个缓冲区,记录当前发送或接收到的数据。接收端会在返回的ACK报文中包含自己可用于接收数据的缓冲区的大小,在TCP的报文首部里用window表示。发送端发送的数据不会超过window的大小。

1.3 零窗口

  • 如果接收端处理过慢,那么window可能变为0,这种情况下发送端就不再发送数据了。为此TCP使用了ZWP(Zero Window Probe,零窗口探针)技术。具体是在发送端引入一个计时器,每当收到一个零窗口的应答后就启动该计时器。每间隔一段时间就主动发送报文,由接收端来调整ACK中返回的窗口大小。若接收者持续返回零窗口(一般是 3 次),则有的TCP实现会发送RST断开连接。

2. 拥塞控制

2.1 目的

  • 当等待接收端的ACK超时、或者收到乱序包时,说明网络出现了拥塞。TCP通过各种协同工作的机制来解决网络拥塞。

2.2 策略

  • 发送端维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。下面用报文段个数作为cwnd的值进行说明,实际的cwnd是以字节为单位的。
  • 在这里插入图片描述
2.2.1 慢启动
  • 连接建立时,初始化cwnd = 1,表示可以传一个MSS大小的数据。
  • 每收到一个ACK包,cwnd++。
  • 每经过一个RTT,cwnd会翻倍(指数增长)。
  • 当cwnd >= ssthresh (slow start threshold) 时,进入拥塞避免阶段。
2.2.2 拥塞避免
  • 每收到一个ACK包,cwnd = cwnd + 1/cwnd。
  • 每经过一个RTT,cwnd = cwnd + 1(加性增)。
2.2.3 超时重传

超时重传:如果发送端超时还未收到ACK包,就可以认为网络出现了拥塞,需要解决拥塞

  • 把sshthresh设为当前拥塞窗口的一半(乘性减)。
  • cwnd 重置为1,重新开始慢启动过程。
2.2.4 快速重传

快速重传:接收端收到乱序包时,会发送duplicate ACK通知发送端。当发送端收到3个duplicate ACK时,就立刻开始重传,而不必继续等待到计时器超时。快速重传会配合快速恢复算法:

  • 把sshthresh设为当前拥塞窗口的一半(乘性减)。
  • cwnd重置为sshthresh,重新开始拥塞避免过程。

为什么快速重传不需要像超时重传那样,将 cwnd 重置为1重新开始慢启动呢?

  • 因为它认为如果网络出现拥塞的话,是不会收到好几个重复的ACK的,所以现在网络可能没有出现拥塞。

三、TCP的粘包问题

1. 基本概念

  • 粘包:多个数据包被连续存储于连续的缓存中,接收方在对数据包进行读取时由于无法确定发送方的发送边界,而采用某一估测值大小来进行数据读出,因此,就可能出现读入的数据不是完整的数据包情况,会导致读入数据中同时包括前一个数据包的尾部和后一个数据包的首部,即粘包现象。

2. 产生原因

  • 发送方:由TCP协议本身造成
    1. TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。
    2. TCP协议规定,如果数据包过长就会被分开传输。这样接收方就收到了粘包数据。
  • 接收方:接收方用户进程不及时接收数据
    1. 接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。

3. 解决方式

  • 发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。
  • 发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
  • 可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

四、TCP和UDP的对比

TCPUDP
连接性面向连接无连接
可靠性可靠不可靠
传输方式面向字节流,TCP将要发送的数据视为无结构的字节流,如果发送的数据太长,就拆分发送,如果发送的数据太短,则积累较多的字节后再发送。面向报文(保留报文的边界),发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。UDP 一次发送一个报文,不管多大,都以报文为发送单位。
传输速度
双工性全双工一对一、一对多、多对一、多对多
流量控制 / 拥塞控制
应用场景对效率要求相对低,但是对准确性要求高的场景;或是要求有连接的场景。如文件传输、发送邮件等对效率要求相对高,对准确性要求相对低的场景。如即时通信、直播等
应用层协议SMTP(电子邮件)、TELNET(远程登录控制)、HTTP、FTPDNS、TFTP(文件传输)、DHCP(动态主机配置)…
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值