1.TCP和UDP的区别
(1)TCP
TCP 提供面向连接的服务:在传送数据之前必须先建立连接,数据传送结束后要释放连接。
TCP 具有可靠性:传递数据之前有三次握手来建立连接,而且在数据传递时有窗口、重传、拥塞控制机制,在数据传完后需要断开连接用来节约系统资源。因此,TCP可以提供可靠的面向连接服务,但是这些操作增加了许多开销,例如流量控制、计时器、连接管理等。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。
(2)UDP
UDP 不具有可靠性。UDP 在传递数据之前不需要先建立连接,远地主机在收到 UDP 报文后,不需要给出任何确认。UDP 一般用于即时通信,例如: QQ 语音、 QQ 视频 、直播等等。
2.UDP 首部格式
UDP 首部字段只有 8 个字节,包括源端口、目的端口、长度、检验和。12 字节的伪首部是为了计算检验和临时添加的。
3.TCP 首部格式
①源端口:本端口号,即发起请求的端口号;
②目的端口:接收请求的端口号;
③序号 :报文段的编号,即字节流的编号。例如:序号为 301表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的序号应为 401;
④确认号 :期望收到下一个报文段的序号。例如: B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701;
⑤数据偏移 :数据部分与报文段起始处的偏移量,实际上指的是首部的长度;
⑥同步 SYN :在连接建立时用来同步序号。当 SYN=1,ACK=0 时表示这是一个连接请求报文段。若对方同意建立连接,则响应报文中 SYN=1,ACK=1;
⑦确认 ACK :当 ACK=1 时确认号字段有效,否则无效。TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置 1;
⑧终止 FIN :当 FIN=1 时,表示发送方的数据已发送完毕,并要求释放连接;
⑨窗口 :窗口值是发送窗口的大小。发送方根据接收方的窗口值,设置发送窗口的大小。
4.TCP 的三次握手
说明:SYN表示建立连接(0/1),ACK表示确认(0/1),seq是指本端的确认序号,ack是指对端的确认序号+1
① 服务端 B 处于LISTEN监听状态,等待客户端 A 的请求。
② 客户端 A 向 服务端 B 发送建立连接的请求报文,SYN=1,本端确认序号seq=x;客户端 A 进入SYN_SENT状态。
③ 服务端 B 接收到第一次握手的请求报文。如果同意建立连接,则向 A 发送连接确认报文:SYN=1,ACK=1,本端确认序号seq=y,对端确认序号ack=x+1;服务端 B 进入SYN_SENT状态。
④ 客户端 A 接收到第二次握手的连接确认报文,并向 B 发送报文:ACK=1, 本端确认序号seq=x+1,对端确认序号ack=y+1;客户端 A 进入ESTAB_LISHED状态。
⑤ 服务端 B 接收第三次握手的确认报文后,连接建立;服务端 B 也进入ESTAB_LISHED状态。
(1)CLOSED状态
CLOSED是初始状态,表示TCP连接是“关闭着的”或”未打开的”。
(2)LISTEN状态
LISTEN表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接 。
(3)SYN_SENT状态
SYN_SENT是客户端第一次发给服务端的时候设置成的状态。
(4)SYN_RCVD状态
SYN_RCVD是TCP三次握手的中间状态,是服务端收到SYN包并发送[SYN,ACK]包后所处的状态。
SYN攻击:利用TCP协议缺陷,通过发送大量的半连接请求,耗费服务器CPU和内存资源。SYN_RCVD很短暂,但是遇到SYN攻击时,会出现大量的这种状态,即收不到三次握手最后一个客户端发来的ACK,所以一直是这个状态,不会转换到ESTAB_LISHED状态。
(5)ESTAB_LISHED状态
ESTAB_LISHED表示TCP连接已经成功建立,开始传输数据。
问题1:TCP三次握手中为什么客户端最后还要发送一次确认?( 即TCP为什么需要三次握手)
防止已经失效的连接请求报文突然又传送到了服务器,让服务器错误打开连接。
如果使用的是两次握手建立连接。假设有这样一种场景:客户端发送第一握手请求并且没有丢失。网络问题导致TCP的客户端迟迟没有收到客户端返回的第二次握手请求。因此,客户端重新向服务端发送第一次握手请求,此后客户端和服务端经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务端,这个报文本该是失效的,但是两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
问题2:第2次握手传回了ACK,为什么还要传回SYN?
第2次握手的时候,服务端返回ACK给客户端,目的是告诉客户端:服务端确实收到客户端第一次握手的信号,表明客户端到服务端的通讯是正常的。回传SYN的目的:建立并确认服务端到客户端的通信。
SYN 是 TCP/IP 建立连接时使用的握手信号。在客户端和服务端之间建立正常的 TCP 网络连接时,客户端首先发出一个 SYN 消息,服务端使用 SYN-ACK 应答表示接收到了这个消息,最后客户端再以 ACK 消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。
5.TCP 的四次挥手
说明:FIN表示关闭连接(0/1)
① 客户端 A 和服务端 B 都处于ESTAB_LISHED数据传输状态。
② 客户端 A 向 服务端 B 发送确认的请求报文:FIN=1,本端确认序号seq=u;客户端 A 进入FIN_WAIT_1状态。
③ 服务端 B 接收到第一次挥手的请求报文。如果同意关闭连接,则向 A 发送连接确认报文:ACK=1,本端确认序号seq=v,对端确认序号ack=u+1;服务端 B 进入CLOSE_WAIT状态。
④ 客户端 A 接收到第二次挥手的请求报文;客户端 A 进入FIN_WAIT_2状态。
⑤ 服务端 B 向客户端 A 发送关闭连接的请求报文:FIN=1,ACK=1,本端确认序号seq=w,对端确认序号ack=u+1;服务端 B 进入LAST_ACK状态。
⑥ 客户端 A 接收到第三次挥手的请求报文,并向服务端 A 发送报文:ACK=1,seq=u+1,ack=w+1;客户端 A 进入TIME_WAIT状态,等待2MSL后进入CLOSED状态。
⑦ 服务端 B 接收到第四次挥手的请求报文;服务端 B 进入CLOSED状态。
(1)FIN_WAIT_1 状态
FIN_WAIT_1表示客户端第一次等待服务端ACK的确认请求报文。当客户端主动关闭连接时,向服务端发送FIN报文,此时客户端进入FIN_WAIT_1的状态。当服务端回复ACK,确认关闭后,则客户端进入FIN_WAIT_2的状态。因此,客户端只有在没有收到服务端ACK的情况下,才会处于FIN_WAIT_1状态。
(2)CLOSE_WAIT 状态
CLOSED_WAIT表示服务端正在等待关闭。该状态主要目的是让服务端发送还未传送完毕的数据,传送完毕之后服务端才会向客户端发送FIN的关闭确认报文。
(3)FIN_WAIT_2 状态
FIN_WAIT_2表示客户端第二次等待服务端的FIN关闭请求报文。
(4)LAST_ACK 状态
LAST_ACK表示服务端等待最后的关闭确认报文。客户端向客户端发送FIN的关闭请求报文后,等待最后的关闭确认报文。
(5)TIME_WAIT 状态
TIME_WAIT表示客户端最后定时关闭的状态。客户端接收到FIN后,从FIN_WAIT_2状态进入到TIME_WAIT状态,直到定时时间到后,进入CLOSED状态。
问题1:TCP为什么要四次挥手?
客户端发送 FIN 连接关闭的请求报文之后,服务端收到了该报文进入了CLOSE-WAIT状态。CLOSE-WAIT状态主要是为了让服务端发送还未传送完毕的数据,传送完毕之后服务端才会向客户端发送FIN连接关闭的确认报文。
问题2:TCP四次挥手中为什么客户端最后还要等待2MSL?
客户端接收到服务端的 FIN 报文后进入TIME_WAIT状态,而不是直接进入CLOSED状态,还需要等待一个时间计时器设置的时间2MSL。理由如下:
① 确保最后一个确认报文能够到达。如果服务端没收到客户端发送来的确认报文,那么就会重新发送FIN连接请求报文,客户端等待一段时间就是为了处理这种情况的发生。
② 让本次关闭连接的持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。
问题3:TCP三次挥手和四次挥手的抓包数据是怎样的?
6.TCP 的可靠性传输
(1)校验和
TCP首部有16byte的校验和字段,校验内容包括TCP首部和数据部分。计算方法为:客户端将整个报文段分为多个16位的段,然后将所有段进行反码相加,将结果存放在检验和字段中;服务端采用相同的方法进行计算,如果最终结果为校验和字段所有位是全1则正确,否则存在错误。
(2)序列号和确认应答机制
TCP中每条数据都有编号,即序列号。
TCP的首部中有一个确认字段ACK,此标志位表示确认号是否有效,即确认之前的数据都按序达到。例如:ACK=1、ack=1001表示确认有效,将要发送的报文序号是1001
(3)超时重传机制
如果一个已经发送的报文段在超时时间内没有收到确认,那么就重传这个报文段(通常情况发送方在发出报文段后启动定时器,如果到点了还没有收到响应报文,则进行重传)。
①情况一:发送方的报文丢失
② 响应的ACK丢失
问题1:如何识别出重复的数据?
使用序列号判断是否重复。当接收方接收到重复的数据时就将其丢掉,重新发送ACK。
问题2:如何确定重传时间?
报文段发出到收到应答中间有一个报文段的往返时间RTT,超时重传时间RTO大于RTT。TCP根据网络情况动态的计算RTT,即RTO是不断变化的。在Linux中,超时以500ms为单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。规律为:如果重发一次仍得不到应答,就等待2500ms后再进行重传,如果仍然得不到应答就等待4500ms后重传,依次类推,以指数形式递增,重传次数累计到一定次数后,TCP认为网络或对端主机出现异常,就会强行关闭连接。
(4)连接管理
连接管理机制:TCP建立连接时的三次握手、TCP断开连接时的四次挥手。
(5)流量控制
如下 7.TCP 的滑动窗口和流量控制
(6)阻塞控制
如下 8.TCP 的拥塞控制
7.TCP 的窗口机制和流量控制
TCP 利用滑窗口实现流量控制。流量控制的目的是控制发送方发送速率,保证接收方来得及接收。
TCP报文段首部有16位窗口字段,当接收方收到发送方的数据后,ACK响应报文中就将自身缓冲区的剩余大小设置到放入16位窗口字段。该窗口字段值是随网络传输的情况变化的,窗口越大,网络吞吐量越高。如果缓冲区满,就将窗口置为0,发送方收到后就不再发送数据,但是需要定期发送一个窗口探测数据段,使得发送方知道接收方的窗口大小。
发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。
TCP窗口的数据交互流程如下:
8.TCP 的拥塞控制
网络拥塞可能导致分组丢失。发送方会继续重传,从而导致网络拥塞程度更高。因此,当网络拥塞时,应该控制发送方的速率(这一点与流量控制类似,但是出发点不同:流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度)。
TCP协议主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。