目录
41.为什么每次建立TCP连接时,初始化的序列号都不一样?
42.初始序列号ISN如何随机产生?
43.既然IP层会分片,为什么TCP层需要根据MSS分片呢?
44.TCP第一次握手丢失,会发生什么?
45.TCP第二次握手丢失,会发生什么?
46.TCP第三次握手丢失,会发生什么?
47.什么是SYN攻击?如何避免SYN攻击?
48.TCP四次挥手过程?
49.第一次挥手丢失了,会发生什么?
50.第二次挥手丢失了,会发生什么?
51.第三次挥手丢失了,会发生什么?
52.第四次挥手丢失了,会发生什么?
53.为什么TIME_WAIT时间是2MSL?
54.为什么需要TIME_WAIT状态?
55.服务器出现大量TIME_WAIT的原因有哪些?
56.服务器出现大量CLOSE_WAIT状态的原因?
57.如果已经建立了连接,但是客户端突然宕机或者断电了怎么办?
58.如果已经建立了连接,服务端的进程崩溃会发生什么?
59.TCP如何进行Socket编程?
60.connect和accept分别发生在三次握手的哪一步?
41.为什么每次建立TCP连接时,初始化的序列号都不一样?
1)防止历史报文被下一个相同四元组的连接接收;
2)安全性好,防止黑客伪造相同序列号的TCP报文窃取数据。
42.初始序列号ISN如何随机产生?
ISN = M + F(源ip,源端口、目的ip,目的端口)
M:计数器,每4微秒加1;
F:哈希函数,根据源ip,源端口、目的ip,目的端口生成一个随机数。
Tips:序列号(SEQ)是一个32位的无符号数,初始化序列号(ISN)可以被视为一个32位的计数器,它们都不是无限递增的,都会发生回绕为初始值的情况,所以无法通过序列号来判断数据传输的数据是新数据还是老数据。
43.既然IP层会分片,为什么TCP层需要根据MSS分片呢?
先介绍两个概念:
MTU:网络包的最大长度,一般1500字节。
MSS:除去IP头和TCP头之后,包能容纳数据的最大长度。
如果TCP的整个报文(TCP头+TCP数据)交给IP层分片,由于IP层没有超时重传机制,当某一个IP分片丢失了, 目的主机无法组成完整的报文,就不能响应ACK给发送端,则会触发TCP的超时重传机制,TCP层就会重新发送整个TCP报文,重新发送全部的IP分片,重传的效率很低。
如果TCP层根据MSS分片,分片后的数据 + TCP头 + IP头的长度小于MTU,所以不用MTU分片,当某个TCP分片丢失后,只用重传该分片,提高了重传效率。
44.TCP第一次握手丢失,会发生什么?
第一次握手报文发送后,客户端迟迟收不到服务端发送的第二次握手报文,就会触发超时重传机制,重传的SYN报文的序列号都是一样的。
每次重传的时间都是上一次重传时间的2倍。当客户端的重传次数达到最大重传次数后,再等待一段时间(上一次超时时间的2倍),如果还没有收到第二次握手报文,客户端就断开连接。
45.TCP第二次握手丢失,会发生什么?
客户端会认为自己的第一次握手报文丢失,会触发超时重传机制,重传SYN报文;服务端迟迟收不到第三次握手报文,也会触发超时重传机制,重传SYN-ACK报文。
当双端都达到最大重传次数后,各自都等待一段时间(上次超时时间的2倍),如果还没有收到对应的报文,则各自都会断开连接。
46.TCP第三次握手丢失,会发生什么?
客户端收到SYN-ACK报文后,就会进行第三次握手,发送ACK报文给服务端,客户端进入ESTABLISHED状态。
服务端迟迟收不到ACK报文,服务端就会触发超时重传,重传SYN-ACK报文,直到收到第三次握手,或者达到最大重传次数,一直收不到则会断开连接。
47.什么是SYN攻击?如何避免SYN攻击?
SYN攻击:攻击者短时间内伪造不同ip发送SYN报文和服务器进行第一次握手,服务端收到SYN报文后,创建半连接队列(SYN队列)并将该连接加入队列中,服务器发送SYN-ACK报文给攻击者进行第二次握手,攻击者不发送ACK给服务器进行第三次握手,导致服务器的半连接队列装满,后续收到SYN报文就丢弃,此时服务器就无法和真正的客户端建立连接。
避免SYN攻击的方式:
1)增大TCP半连接队列;
2)开启net.ipv4.tcp_syncookies:绕过SYN半连接就直接建立TCP连接;
3)减少SYN-ACK报文最大重传次数:超出最大重传次数后就断开连接。
4)调大netdev_max_backlog:该值设置保护队列的大小,当网卡接收数据包的速度 > 内核处理数据的速度时,就会将数据包放入保护队列中。
48.TCP四次挥手过程?
第一次挥手:客户端想与服务端断开连接,就会发送FIN=1的报文给服务端,客户端由ESTABLISHED -> FIN_WAIT_1;
第二次挥手:服务端收到报文后,发送ACK报文给客户端,服务端由ESTABLISHED -> CLOSED_WAIT;
客户端收到ACK后,由FIN_WAIT_1 -> FIN_WAIT_2;
第三次挥手:当服务端没有数据要传输时,就会发送FIN=1的报文给客户端,服务端由CLOSE_WAIT -> LAST_ACK;
第四次挥手:客户端收到FIN报文后,就会发送ACK报文给服务端,客户端由FIN_WAIT_2 -> TIME_WAIT;
服务端收到客户端的ACK报文后,由LAST_ACK -> CLOSE,服务端完成连接关闭;
客户端经过2MSL后,自动进入CLOSE状态,客户端也完成连接关闭。
49.第一次挥手丢失了,会发生什么?
客户端发送FIN后,状态由ESTABLISH -> FIN_WAIT_1,若迟迟收不到服务端的ACK报文,就会触发超时重传机制,如果重传次数到达了最大重传次数后,再等待一段时间(上一次超时时间的2倍)后,没有收到ACK就直接进入CLOSE状态。
50.第二次挥手丢失了,会发生什么?
服务端发送ACK报文后状态由ESTABLISH -> CLOSE_WAIT。因为ACK报文是不会重传的。所以客户端会触发重传机制,重新发送FIN报文,重传次数到达最大重传次数后,如果一直没有收到ACK,就直接进入CLOSE状态。
小Tips:如果客户端收到ACK后,客户端状态由FIN_WAIT_1 -> FIN_WAIT_2(该状态有时间限制),之后等待第三次挥手,等待服务端的FIN报文。如果客户端断开连接使用的是close()函数(使用此函数后不可以再收发数据了),那么如果迟迟收不到服务端的FIN报文,则会在默认值60秒后自动断开连接,进入CLOSE状态;如果客户端断开连接使用的是shutdown()函数(使用此函数还可以接收数据),那么如果客户端收不到服务端的FIN报文,就会进行死等。。。。
51.第三次挥手丢失了,会发生什么?
服务端发送FIN报文后,状态由CLOSE_WAIT -> LAST_ACK。客户端此时处在FIN_WAIT_2状态(该状态有时间限制)。如果服务端迟迟收不到客户端的ACK报文,就会进行超时重传重新发送FIN报文,如果达到最大超时重传次数后,等待一段时间(上一次超时时间的2倍)后,还没收到ACK报文,服务端就会断开连接。客户端也会在默认值60秒后关闭连接(调用close()函数的情况下)。
52.第四次挥手丢失了,会发生什么?
客户端收到FIN后,回复ACK报文,状态由FIN_WAIT_2 -> TIME_WAIT状态,开启2MSL的定时器。服务端此时处于LAST_ACK状态,迟迟收不到ACK就会超时重传发送FIN报文给客户端,客户端收到FIN后重新发送ACK,并重置定时器,重新等待2MSL。服务端到达最大重传次数后,等待一段时间后(上一次超时时间的2倍),服务端就会自动关闭连接。客户端也会在2MSL后断开连接。
53.为什么TIME_WAIT时间是2MSL?
MSL(Maximum Segment Lifetime,报文在任何网络上的最大生存时间)。任何报文超过这个时间就会被丢弃。
当发送方将数据包发送给接收方后,到接收方收到这个数据需要花费1MSL,接收方回应数据给发送方直到接收方收到数据也需要1MSL,所以一来一回就需要2MSL。
2MSL时间可以至少允许网络中的报文丢失一次。若第四次挥手的ACK报文在一个MSL内丢失了,则被动关闭方重发的FIN会在第2个MSL内到达,此时可以客户端会重新计时2MSL,并回复ACK报文。
54.为什么需要TIME_WAIT状态?
主动关闭方,才会有TIME_WAIT状态!!!
1)2MSL能够保证原来连接里的数据都完全的消失,防止历史连接中的数据被后面相同的四元组连接错误的接收,产生数据混乱的问题;
2)保证被动关闭方可以正确的关闭。
55.服务器出现大量TIME_WAIT的原因有哪些?
1)HTTP没有使用长连接:检查客户端和服务端是否都开启了HTTP Keep-Alive
2)HTTP长连接超时:检查是否是因为网络问题,导致客户端发送的数据一直没有被服务端接收到,以至于 HTTP 长连接超时
3)HTTP长连接的请求数量达到上限:调大服务器软件的请求数量
56.服务器出现大量CLOSE_WAIT状态的原因?
CLOSE_WAIT状态是被动关闭方才有的。因为服务器没有调用close()函数关闭连接,无法由CLOSE_WAIT -> LAST_ACK。
没有调用close()函数的可能原因:
1)没有将服务端的监听socket注册到epoll;
2)没有将新连接进行accept;
3)没有将已经连接的socket注册到epoll;
4)客户端要断开连接,服务端没有调用close()关闭连接。
57.如果已经建立了连接,但是客户端突然宕机或者断电了怎么办?
在一段时间内没有任何连接相关的活动,TCP的保活机制开始起作用。每隔一段时间就会发送一个探测报文给对端,该探测报文的数据非常少,如果连续几个探测报文都没有回应,则默认该TCP连接死亡,系统内核将错误信息通知给上层应用程序。
应用程序若想使用 TCP 保活机制需要通过 socket 接口设置SO_KEEPALIVE选项才能够生效,如果没有设置,那么就无法使用 TCP 保活机制。
情况1:客户端正常,服务端发送探测报文后,对端正常响应,TCP保活时间会被重置,等待下一次保活机制的启动。
情况2:客户端宕机并重启,服务端发送探测报文发给对端是会响应的,但是没有该连接的有效信息,会产生一个RST报文,就会发现该连接已被重置。
情况3:客户端宕机,服务端发送连续的探测报文都没有响应,则表明该TCP连接已经死亡。
58.如果已经建立了连接,服务端的进程崩溃会发生什么?
当服务端的进程崩溃后,内核会回收该进程的所有TCP连接资源,内核会发送第一次挥手FIN报文给客户端,后续的挥手过程也是有内核完成,所以即使进程崩溃了,也可以与客户端完成四次挥手。
59.TCP如何进行Socket编程?
60.connect和accept分别发生在三次握手的哪一步?
客户端connect函数调用发生第一次握手,accept调用发生第二次握手,connect成功返回表示第二次握手完成,accept成功返回表示第三次握手成功。