1:TCP三次握手和四次挥手
-
1.1:TCP的头部结构
主要参数说明:- 序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
- 确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。
- 标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN,具体含义如下:
(A)URG:紧急指针(urgent pointer)有效。
(B)ACK:确认序号,当ACK=1代表确认序号有效。
(C)PSH:接收方应该尽快将这个报文交给应用层。
(D)RST:重置连接。
(E)SYN:发起一个新连接,当SYN=1代表有效。
(F)FIN:释放一个连接,当FIN=1代表有效。
-
1.2:三次握手其实就是指建立一个TCP连接时,确认双方的接收能力和发送能力都是正常的。如下图
-
1.3:三次握手的五个问题
-
为什么需要三次握手,两次不行吗?
答:弄清这个问题,我们需要先弄明白三次握手的目的是什么,能不能只用两次握手来达到同样的目的。
第一次握手:客户端发送网络包,服务端收到了。
这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
第二次握手:服务端发包,客户端收到了。
这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:客户端发包,服务端收到了。
这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
因此,需要三次握手才能确认双方的接收与发送能力是否正常。
试想如果是用两次握手,则会出现下面这种情况:如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,此时没有第三次握手了,于是建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。
-
什么是半连接队列?
答:服务器第一次收到客户端的SYN之后,就会处于SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。
当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。
这里在补充一点关于SYN-ACK 重传次数的问题:
服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。
注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s… -
ISN(Initial Sequence Number)是固定的吗?
答:当一端为建立连接而发送它的SYN时,它为连接选择一个初始序号。ISN随时间而变化,因此每个连接都将具有不同的ISN。ISN可以看作是一个32比特的计数器,每4ms加1 。这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它做错误的解释。三次握手的其中一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便让对方知道接下来接收数据的时候如何按序列号组装数据。如果 ISN 是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的。 -
三次握手过程中可以携带数据吗?
答:其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据。
为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据。因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。也就是说,第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。 -
SYN攻击是什么?
答:服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。
检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。
-
-
1.4:四次挥手
建立一个连接需要三次握手,而终止一个连接要经过四次挥手。这由TCP的半关闭造成的。所谓的半关闭,是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。 -
1.5:挥手为什么需要四次?
答:关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文我收到了”。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。
2:TCP和UDP对比
选项 | TCP | UDP |
---|---|---|
可靠性 | 全双工可靠传输无差错,不丢失,不重复,且按序到达 | 尽最大努力交付 |
建立连接 | 需要建立连接 | 无需建立连接 |
数据发送模式 | 面向字节流 | 面向报文 |
传输方式 | 点对点(不支持广播和多播) | 一对一,一对多,多对一,多对多 |
首部开销 | 20字节 | 8字节 |
拥塞机制 | 有 | 无 |
流量控制 | 有 | 无 |
系统资源占用 | 对系统资源要求较多 | 对系统资源要求较少 |
实时性 | 相对UDP较低 | 较高,适用于对高速传输和实时性要求较高的通信或广播通信 |
确认重传机制 | TCP提供超时重发,丢弃重复数据,检验数据, | 无重传,只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地 |
应用场景总结
TCP:效率要求相对低,但对准确性要求相对高的场景。因为传输中需要对数据确认、重发、排序等操作,相比之下效率没有UDP高。举几个例子:文件传输(准确高要求高、但是速度可以相对慢)、接受邮件、远程登录。
UDP:效率要求相对高,对准确性要求相对低的场景。举几个例子:QQ聊天、在线视频、网络语音电话(即时通讯,速度要求高,但是出现偶尔断续不是太大问题,并且此处完全不可以使用重发机制)、广播通信(广播、多播)