目录
5.3 用户数据报协议UDP(User Datagram Protocol)
5.4 传输控制协议TCP(Transmission Control Protocol)
TCP为应用层协议提供可靠传输,发送端按顺序发送,接收端按顺序接收,其间发送丢包、乱序,TCP负责重传和排序。下面是TCP的应用场景。
- 多次交互:客户端程序和服务端程序需要多次交互才能实现应用程序的功能
- 接收电子邮件的POP3
- 发送电子邮件的SMTP
- 传输文件的FTP
- 数据需要分段传输:应用程序传输的文件需要分段传输
- 浏览器访问网页:网页中图片和HTML文件需要分段后发送给浏览器
- QQ传文件
- 数据无需分段传输:客户端程序和服务端程序通信,应用程序发送的数据包不需要分段。
- DNS域名解析:客户端向DNS服务器发送一个报文解析某个网站的域名,DNS服务器将解析的结果使用一个报文返回给客户端。
- 实时通信:发送端和接收端需要实时交互,不允许较长延迟(通信时无需建立连接)
- 语音/视频聊天:即便有几句话因为网络堵塞没听清,也不允许使用TCP等待丢失的报文,等待的时间太长了,就不能愉快的聊天了。
- 多播或广播通信:
- 学校多媒体机房:老师的电脑屏幕需要教室的学生电脑接收屏幕,在老师的电脑安装多媒体教室服务端软件,在学生的电脑安装多媒体教室客户端软件。老师电脑使用多播地址或广播地址发送报文,学生电脑都能收到。
通常,传输层协议加一个端口号来标识一个应用层协议。
- 常见的应用层协议和传输层协议
- HTTP默认使用TCP的80端口
- HTTPS默认使用TCP的443端口(访问安全网站)
- FTP默认使用TCP的21端口
- SMTP默认使用TCP的25端口
- POP3默认使用TCP的110端口
- Telnet使用TCP的23端口
- RDP默认使用TCP的3389端口(远程桌面协议)
- Windows访问共享资源使用TCP的445端口
- 微软SQL数据库默认使用TCP的1433端口
- MySQL数据库默认使用TCP的3306端口
- DNS使用UDP or TCP 的53端口
端口
- 取值范围:端口用一个16位端口号进行标志,允许有65536个不同的端口号。
- 分类:2大类、3小类
- 服务器端使用的端口号:
- 熟知端口号:0 ~ 1023
- 登记端口号:1024 ~ 49151,为没有熟知端口号的应用程序使用的。使用这个范围的端口号必须在IANA登记,以防止重复。
- 客户端使用的端口号:
- 短暂端口号:49152 ~ 65535,留给客户进程选择暂时使用。
- 当服务器进程收到客户进程的报文时,就知道了客户进程所使用的动态端口号。通信结束后,这个端口号可供其他客户进程以后使用。
- 作用:端口号只具有本地意义,只是为了标志本计算机应用层中的各进程。在互联网中,不同计算机的相同端口号是没有联系的;同一计算机的不同进程使用不同的端口号(唯一)。
- 服务器上端口的作用:定位服务器上的服务
- 服务器给网络中的计算机提供服务,服务器一旦运行某个服务,该服务就会使用TCP/UDP协议的相应端口来侦听客户端的请求、等待客户端的访问,每个服务使用的端口必须唯一。
- 当不同客户端访问同一服务器上的不同应用时,数据报最终都会到达同一服务器。此时,需要使用服务器上的端口号来定位服务,以便将不同的请求转到相应的服务进行处理。
- 客户端上端口的作用:确定数据包返回后给哪个客户端实例
- 注(重要!!!):同一台计算机既可以作为服务端,也可以作为客户端(即服务端和客户端是相对的)。
- 小结:两个计算机中的进程要互相通信,不仅必须知道对方的端口号(为了找到对方计算机中的应用进程) ,而且还要知道对方的 IP 地址(为了找到对方的计算机)。
UDP只在IP的数据报服务之上增加了很少一点的功能:
- 功能1(复用和分用):使用端口标识不同的应用层协议
- 注:如果不是为了复用和分用,应用程序完全可以将需要传输的报文交给网络层,而不需要经过传输层UDP。
- 功能2(差错检测)
- 面向无连接:发送数据之前不需要建立连接
- 减少了开销:主机不需要维持复杂的连接状态表(含有许多参数)
- TCP:主机需要记录所有的TCP连接,可使用命令“netstat”查看(当大量用户同时访问web服务器时,web服务器需要记录所有的会话状态,消耗服务器的资源)
- UDP:
- 减少了时延
- 面向报文:对于应用层交下来的报文,UDP既不合并,也不拆分,而是保留这些报文的边界。UDP一次交付一个完整的报文。
- 尽最大努力交付/不提供可靠交付:
- 注:UDP本身是不保证可靠的,当发送的数据出现差错时,由发送端重新发送。
- 不局限于一对一:UDP支持一对一、一对多、多对一和多对多的交互通信(即支持多播、广播)
- 无拥塞控制:网络出现的拥塞不会使源主机的发送速率降低(减少了时延)
- 实时应用:要求源主机以恒定的速率发送数据,并且允许在网络发生拥塞时丢失一些数据,但却不允许数据有太大的时延。
- 多媒体通信
- 首部开销小:
- UDP:8个字节
- TCP :20个字节
- 面向连接:发送数据之前需要建立连接(三次握手),用于协商参数(窗口大小、最大报文段长度MSS、是否支持选择性确认等)
- 面向字节流:虽然应用程序和TCP的交互是一次一个数据块,但TCP把应用程序交下来的数据看成仅仅是一连串无结构的字节流。TCP中的“流”(steam)指的是流入到进程或从进程流出的字节序列。
- 数据块不同:TCP不保证接收方应用程序收到的数据块和发送方应用程序发出的数据块具有对应大小的关系。
- 字节流相同:TCP保证接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。
- 提供可靠交付:通过TCP连接传送的数据,无差错、不丢失、不重复且按序发送和接收。(为了在无连接的、不可靠的IP网络服务基础之上提供可靠交付的服务,TCP在IP的数据报服务基础之上,增加了保证可靠性的一系列措施。)
- 局限于一对一:每一条TCP连接只能有两个端点(end point),只能是点对点的(一对一)(即不支持多播、广播)
- 全双工通信:一旦通信双方建立连接,就能基于此连接进行双向通信。
TCP中“面向流”的概念
TCP中“连接”的概念
- TCP连接的端点:套接字(socket)/插口
- 套接字由IP地址和端口号构成,表示TCP连接的一端。
- 注1:TCP 连接的端点不是主机,不是主机的IP 地址,不是应用进程,也不是运输层的协议端口。
- 注2:socket有多种不同的意思
- 应用编程接口API称为socket API,简称为socket
- socket API中使用的一个函数名也叫作socket
- 调用socket函数的端点称为socket
- 调用socket函数时其返回值称为socket描述符,简称为socket
- 在操作系统内核中连网协议的Berkeley实现,称为socket实现
- TCP连接:每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定。(每一条TCP连接有两个端点)
- TCP 连接就是由协议软件所提供的一种抽象。
- TCP 把连接作为最基本的抽象。
- 同一个IP地址可以出现在多个不同的TCP连接中。
- 同一个端口号可以出现在多个不同的TCP连接中。
- 示例:现有两个浏览器同时访问web服务器,建立的连接如下所示
- 连接1:{(202.108.22.5:80), (192.168.0.2:55262)}
- 连接2:{(202.108.22.5:80), (192.168.0.3:59379)}
- 可见,同一个IP地址202.108.22.5出现在两条不同的连接中;同一个端口号80也出现在两条不同的连接中。
理想的传输条件应该具备以下两个特点:
- 特点1:传输信道不产生差错。
- 特点2:不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据。
在理想传输条件下,不需要采取任何措施就能够实现可靠传输。然而,实际的网络都不具备以上两个理想条件,因此必须使用一些可靠传输协议,在不可靠的传输信道实现可靠传输。
工作原理1:停止等待协议(不采用)
自动重传请求ARQ (Automatic Repeat reQuest)
- 工作原理:发送方每发送完一个分组就停止发送,等待接收方的确认。在收到确认后,发送方再发送下一个分组。
- 自动重传请求的含义:重传的请求是自动进行的,接收方不需要请求发送方重传某个出错的分组。
- 注1:通常,接收方最终总是可以收到对所有发出分组的确认。如果发送方不断重传分组但总是收不到确认,就说明通信线路太差,不能进行通信。
- 注2:在发送完一个分组后,必须暂时保留已发送的分组的副本,以备重发。
- 注3:超时计时器的重传时间应当比数据在分组传输的平均往返时间更长一些。
全双工通信的双方既是发送方也是接收方。为了讨论问题的方便,我们仅考虑A发送数据,而B接收数据并发送确认(即A叫做发送方,B叫做接收方)。
- Case1:无差错情况
- 发送的数据报安全到达接收方
- 确认的数据报也安全到达发送方
- Case2:超时(自动)重传
- 发送的数据报 出现 差错或丢失
- Case3(确认丢失):发送方超时重传;接收方丢弃重复的数据报
- 发送的数据报安全到达接收方
- 确认的数据报丢失
- Case4(确认迟到):发送方超时重传,不处理迟到的确认;接收方丢弃重复的数据报
- 发送的数据报安全到达接收方
- 确认的数据报迟到(路由较远)
- 小结:
- 发送方:当收到同一个数据报的多次确认时,后面的确认不做任何处理
- 接收方:当收到同一个数据报时,丢弃重复
- 特点:
- 停止等待:发送方每次只发送一个分组;在收到确认后再发送下一个分组。
- 编号:分组和确认分组都必须进行编号(序号、确认号)。
- 自动重传请求:发送方为每个发送的分组设置一个超时计时器。若超时计时器超时,发送方会自动重传分组。
- 优缺点:
- 优点:简单
- 缺点:信道利用率太低
- 往返时间RTT≫ 分组发送时间TD:信道利用率就会非常低
- 重传:对传送有用的数据信息而言,信道利用率就还要降低
工作原理2:改进的停止等待协议(采用)
连续ARQ协议和滑动窗口协议
- 问题引入:自动重传请求的信道利用率低
- 解决方案:连续自动重传请求 或 流水线传输
- 工作原理:发送方可连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。
- 由于信道上一直有数据不间断地传送,这种传输方式可获得很高的信道利用率。
具体实现1:以字节为单位的滑动窗口技术(改进的停止等待协议)
- 所谓的窗口,就是接收端允许发送端当前所能够发送的数据量。发送方将窗口内的数据量进行分段,并依次发送给接收端。
- 接收端窗口移动的原则:不能跳过未收到的数据段(一旦跳过,则表明已经收到,且应用程序已经读取,可以删除接收端对应的缓存数据)
- 发送端窗口移动的原则:不能跳过未确认的数据段(一旦跳过,则表明已经确认,可以删除发送端对应的缓存数据)
具体实现2:超时重传时间的选择或调整
- 超时重传时间并不是固定不变的,而是根据网络的状况、双方的距离等因素 进行 动态计算调整。
- 发送方和接收端处于同一网段(交换机直接相连)、网络状况较好 → 往返传输时间RTT较短 → 超时重传时间就不能太长(否则,数据丢失时需要经过较长时间才能重传)
- 发送方和接收端处于不同网段(途径多个路由器)、网络状态较差 → 往返传输时间RTT较长 → 超时重传时间就不能太短(否则,大部分的数据都会超时重传)
- Step1:测量TCP往返传输时间RTT(新的RTT样本)
- 方式1:TCP首部的选项字段Timestamp
- 方式2:重传队列中数据包的TCP控制块
- 方式3:建立TCP连接时就能计算出RTT
- Step2:计算新的RTT(为Step4做准备)
2.125=0.875 ×2+0.125 ×3
- 注1:RFC2988推荐的α=1/8=0.125 (小幅度调整)
- 注2:为什么不直接使用新的RTT样本作为新的RTT呢?因为网络是动态变化的,不能稍有变化就立马改变RTT,而是根据变化进行平滑调整。
- Step3:计算新的RTTD(为Step4做准备)
0.59375=0.75×0.5+0.25×|2.125-3|
- 注1:RFC2988推荐的β=14=0.25
- 注2:RTTD的初始值取为测量到的RTT样本值的一半,后续使用上述公式进行更新(此处假设旧的RTTD为0.5)
- Step4:计算超时重传时间RTO(Retransmission Time-Out)→超时计时器
4.5=2.125+4 ×0.59375
- 注:RTO应大于新的RTT(当然,从公式也可以看出,必然成立)
具体实现3:改进的确认(选择性确认SACK)
- 优点:通过SACK选项可以使TCP发送方只发送丢失的数据,而不用发送后续全部数据,提高了数据的传输效率。
- 正常情况:接收端收到序号为1、101、201、301的数据段,此时只需要给发送端发送确认号为401的数据报即可
- 丢包情况:接收端收到序号为401、501、701的数据段(中间的601数据段未收到)
- 不使用选择确认:接收端给发送端发送确认号为601的数据报(不带有选择确认选项) → 发送端会重新发送序号为601、701的数据段 → 接收端会重复收到序号为701的数据段
- 使用选择确认:接收端给发送端发送确认号为601的数据报(同时带有选择确认选项,含有左右边界) → 发送端只会重新发送序号为601的数据段 → 接收端不会重复收到序号为701的数据段)
- 选择确认最多支持4个不连续的数据段
- 表示边界的最大字节数 = 选项的最大字节数(40字节) – 该选项类型(1字节) – 该选项长度(1字节) = 38字节
- 一个边界占4个字节,一个不连续的数据段占8个字节
- 因此,选择确认最多支持不连续的数据段 = 38字节 / 8字节 = 4.75 → 向下取整为4
利用滑动窗口实现流量控制
接收方给发送方发送确认数据包时,可以同时带有窗口大小,用于调整发送端的窗口大小。
TCP的传输效率
问题1:发送方何时发送数据?
问题2:接收方何时回复确认?
- 问题引入:通信双方建立TCP连接后,只要处于发送窗口内的数据都是被允许发送的。然而,实际通信过程中,会遇到如下几个问题:
- 问题1:当发送窗口内只有较少的数据(极端情况只有1个字节的数据),此时如果组装成一个报文段发送出去,有效数据传输效率就会非常低(见“糊涂窗口综合症”)。
- 问题2:发送方应用程序输入的某个命令(Ctrl+C停止命令),需要接收方立即产生响应,此时如果等待新的数据以凑够MSS字节(通常命令就几个字节),会导致响应延时。
- 问题3:当发送窗口内只有较少的数据,且后续也不会再有新的补充,此时如果一味等待新的数据以凑够MSS字节,则这部分数据将一直发送不出去。
- 解决方案:TCP可以使用不同的机制来控制报文段的发送时机
- 机制1(凑够一包再发):TCP维持一个变量(最大报文段长度MSS),只要缓存中存放的数据达到MSS字节时,就组装成一个TCP报文段发送出去。
- 机制2(命令立即发):由发送方的应用进程指明要求发送报文段,即TCP支持的推送(push)操作。
- 机制3(超时立即发):发送方的一个计时器期限到了,此时就把当前已有的缓存数据装入报文段(但长度不能超过MSS)发送出去。
- 注:如何控制TCP发送报文段的时机仍然是一个较为复杂的问题。
- Nagle算法(发送机制):
- 若发送方应用进程把要发送的数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面到达的数据字节都缓存起来。
- 当发送方收到对第一个数据字节的确认后,再把发送缓存中的所有数据组装成一个报文段发送出去,同时继续对随后到达的数据进行缓存。
- 只有在收到对前一个报文段的确认后才继续发送下一个报文段。
- 当到达的数据已达到发送窗口大小的一半或已达到报文段的最大长度时,就立即发送一个报文段。
- 糊涂窗口综合症(接收机制):
- 发送方糊涂窗口综合症:每次仅发送一个字节或很少几个字节的数据时,有效数据传输效率变得很低的现象。
- 接收方糊涂窗口综合症:接收方应用进程消耗数据太慢(每次只读取一个字节)
- 当接收方的TCP缓冲区已满,接收方会向发送方发送窗口大小为0的报文。
- 若此时接收方的应用进程以交互方式每次只读取一个字节,于是接收方又发送窗口大小为一个字节的更新报文,发送方应邀发送一个字节的数据(发送的 IP 数据报是 41 字节长),于是接收窗口又满了,如此循环往复。
- 解决方案:让接收方等待一段时间,只要出现这两种情况之一,接收方就发出确认报文,并向发送方通知当前的窗口大小。
- Case1:接收缓存已有足够空间容纳一个最长的报文段
- Case2:接收缓存已有一半空闲的空间
- 拥塞控制的原理:当网络中有多个发送端同时发送数据时,会造成链路带宽不够、数据包丢失的现象。此时,如果发送端不理会丢包问题,依旧按照原来的速率发送数据包,就会导致大量丢包数据的重传。因此,与其一味地重传数据包,不如降低发送速率,确保数据包不丢失。
- 正常情况:当输入的负载较少时,发送的流量基本等于链路吞吐量,几乎不丢包
- 轻度拥塞:随着网络中涌入的流量逐渐增多,会出现少量的丢包(此种情况还能接受)
- 拥塞:随着网络中涌入的流量继续增多,会出现大量的丢包,直至死锁
- 拥塞的定义:随着网络中涌入的流量(输入的负载)继续增多,网络的吞吐量不增反降(此种情况应该尽量避免)
- 注:理想情况下,即便涌入网络中的流量非常多,网络应该能通过一定数量的数据包(最大吞吐量),剩余的数据包丢弃。然而,实际情况并非如此,数据包过多会导致路由器忙不过来,从而导致死机的情况(一个数据包都过不去)。
因特网建议标准RFC2581定义了进行拥塞控制的四种算法,即慢开始(Slow-start)、拥塞避免(Congestion Avoidance)、快重传(Fast Restransmit)和快恢复(Fast Recovery),我们假定:(1)数据单方向传送,另外一个方向只传送确认;(2)接收方总是有足够大的缓存空间,因而发送窗口的大小由网络的拥塞程度来决定。
- 拥塞控制的方法1(原始版):慢开始和拥塞避免(1988年提出的TCP拥塞控制算法)
- 缺点:每次出现拥塞,都需要将拥塞窗口调整为1,然后重新进行慢开始,效率不高。
- 拥塞控制的方法2(改进版):快重传和快恢复(1990年新增的两个拥塞控制算法)
- 超时重传(不采用):当数据包丢失时,重传是由发送方来决定的 → 当发送方的超时计时器出现超时,就会自动重传(效率不高)
- 快重传(采用):当数据包丢失时,重传是由接收方来决定的 → 当接收方收到不连续的数据包时,则视为丢包,立即发送3个连续的、重复的确认数据包 → 当发送方收到3个连续的、重复的确认后,就会立即重传,而无需等待超时再重传
- 发送窗口的上限:如果综合考虑(网络对发送方的)拥塞控制和(接收方对发送方的)流量控制,则
- rwnd
:接收方的接收能力 限制 发送方窗口的最大值 - cwnd
:网络的拥塞 限制 发送方窗口的最大值 - 小结:rwnd和cwnd中较小的一个控制发送方发送数据的速率
重点关注:
TCP的连接建立(三次握手)
- 问题1:建立连接时,为什么需要三次握手,两次不行吗?
- 答:
- 数据包1的作用:将客户端的参数(窗口大小、MSS、SACK等)发送给服务器
- 数据包2的作用:服务器确认收到数据包1(客户端的参数);将服务器的参数发送给客户端
- 数据包3的作用:客户端确认收到数据包2(服务器的参数)
- 两次握手的弊端:如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一直等待客户端发送数据,浪费资源。
- 问题2:什么是半连接队列?全连接队列?
- 答:
- 半连接队列(未完成三次握手):服务器第一次收到客户端的SYN之后,就会处于SYN_RCVD状态,此时双方还没有完全建立起连接,服务器会把此种状态下请求连接放在半链接队列里。
- 全连接队列(已完成三次握手):建立起连接的就会放在全连接队列中;如果队列满了就有可能会出现丢包现象。
- SYN-ACK的重传(次数、时间):服务器发送完SYN-ACK包,如果未收到客户端的确认包,服务器进行首次重传,等待一段时间仍未收到客户端的确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s......
- 问题3:三次握手过程中可以携带数据吗?
- 答:第一、二次握手不可以携带数据;第三次握手可以携带数据。
假如第一次握手可以携带数据,如果有人要恶意攻击服务器,那他每次都在第一次握手中的SYN报文中放入大量的数据。因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发SYN报文,这会让服务器花费很多时间、内存空间来接收这些报文。
而对于第三次的话,此时客户端已经处于ESTABLISHED状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。
TCP的连接释放(四次握手/挥手)
(Four-way handshake)
建立一个连接需要三次握手,而终止一个连接要经过四次挥手/四次握手。这由TCP的半关闭(half-close)造成的。所谓的半关闭,就是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。
- 问题1:简述四次挥手的过程?
- 答:假如刚开始双方都处于ESTABLISHED状态,且客户端先发起关闭请求(客户端或服务器均可主动发起挥手动作),则四次挥手的过程如下
- 第一次挥手:客户端发送一个FIN报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态,即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。
- 第二次挥手:服务端收到FIN之后,会发送ACK报文,且把客户端的序列号值+1作为ACK报文的确认号值,表明已经收到客户端的报文了。此时服务端处于CLOSE_WAIT状态,即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。
- 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给FIN报文,且指定一个序列号。此时服务端处于LAST_ACK的状态。 即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。
- 第四次挥手:客户端收到FIN之后,一样发送一个ACK报文作为应答,且把服务端的序列号值+1作为自己ACK报文的序列号值,此时客户端处于TIME_WAIT状态。需要过一阵子以确保服务端收到自己的ACK报文之后才会进入CLOSED状态,服务端收到ACK报文之后,就处于关闭连接了,处于CLOSED状态。 即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。
- 客户端的状态:
- FIN_WAIT1(终止等待1)状态:客户端停止发送数据,主动关闭TCP连接,并已经发出连接释放报文段(FIN报文),此时正在等待服务端的确认
- FIN_WAIT2(终止等待2)状态:客户端已经收到服务端的确认,TCP处于半关闭状态,客户端到服务端的连接释放,此时正在等待服务端发出的连接释放报文段
- TIME_WAIT(时间等待)状态:客户端收到服务端的连接释放报文段后,并对此发出确认报文段(注意,TCP未完全释放掉,还需要经过时间等待计时器设置的时间2MSL)
- CLOSED(关闭)状态:
- 收到一个FIN只意味着在这一方向上没有数据流动。客户端执行主动关闭并进入TIME_WAIT是正常的,服务端通常执行被动关闭,不会进入TIME_WAIT状态。
- 问题2:挥手为什么需要四次?
- 答:因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文(其中,ACK报文是用来应答的,SYN报文是用来同步的)。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端"你发的FIN报文我收到了"。只有等到服务端所有的报文都发送完了,才能发送FIN报文,因此不能一起发送。故需要四次挥手。
- 问题3:简述2MSL等待状态?
- 答:TIME_WAIT状态也成为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime),它是任何报文段被丢弃前在网络内的最长时间。这个时间是有限的,因为TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段。
对一个具体实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)。
这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。这个连接只能在2MSL结束后才能再被使用。
- 问题4:四次挥手释放连接时,等待2MSL的意义?
- 答:MSL是Maximum Segment Lifetime的英文缩写,可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一旦这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
两个理由:
保证客户端发送的最后一个ACK报文段能够到达服务端。 这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,服务端超时重传FIN+ACK报文段,而客户端能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSED状态,若客户端在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则服务端无法正常进入到CLOSED状态。
防止“已失效的连接请求报文段”出现在本连接中。 客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
- 问题5:为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?
- 答:理论上,四个报文都发送完毕,就可以直接进入CLOSE状态了,但是可能网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
TCP的有限状态机
1、三次握手的过程
2、为什么需要三次握手,两次不行吗?
3、什么是半连接队列?
4、ISN(Initial Sequence Number)是固定的吗?
5、三次握手过程中可以携带数据吗?
6、SYN攻击是什么?
7、四次挥手过程
8、挥手为什么需要四次?
9、2MSL等待状态
10、四次挥手释放连接时,等待2MSL的意义?
11、为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?