首页 > 编程知识 正文

tcp协议三次握手四次挥手,tcp三次握手题目

时间:2023-05-03 17:46:55 阅读:33471 作者:4955

1 .信息丢失时:总体原则:

ACK不会重新发送。 SYN和FIN消息段具有最大重发次数。 无论SYN、FIN,达到最大重发次数后,如果对方没有响应,就直接进入关闭状态。

1.1一次握手过程的信息丢失。 正常的三次握手流程:

1.1.1第一次握手协议丢失。 (SYN )通常,当客户端尝试与服务器建立TCP连接时,首先发送第一个SYN段,然后将本地TCP状态设置为SYN_SENT。

随后,如果客户端没有从服务端收到SYN ACK响应,则会触发超时重发机制。

超时时间可能因3358www.Sina.com/OS版本而异。 通常为1秒或3秒,由内核组成,需要重新编译内核才能进行修改。

超时时间判断:内核参数tcp_syn_retries组成,默认值为5,可以手动修改。

重传次数:指数退避计算重发周期,第一次超时重发1秒,第二次超时重发2秒,第三次超时重发4秒,第四次超时重发8秒,第五次超时重发16秒同样,达到最大重发次数后,客户端不重发SYN消息,断开true的connect返回-1,并将错误设置为ETIMEOUT。

[ etime out ] connectionestablishmenttimedoutwithoutestablishingaconnection .达到默认最大重发次数后断开TCP连接时,总时间如下:

1 2 4 8 16 32=63秒,约1分钟。

关于更改TCP内核参数:

所有TCP/IP参数、注意TCP/IP协议系列的所有参数和TCP参数都位于/proc/sys/net目录中。 请注意,此目录中的内容更改是临时的,系统重新启动后所有更改都将丢失。

例如,更改tcp_syn_retries参数:

echo5/proc/sys/net/IP v4/syn _ time out _ retries1.1. 2的第二次握手已丢失。 (SYN ACK )服务器收到客户端的第一个握手syn消息段后,将TCP状态设置为SYN_RECV状态

如果第二次握手的信息段丢失,服务器将开始重新发送。 由于客户端无法接收SYN ACK,无法确定第一个握手的SYN段是丢失了,还是第二个握手的SYN ACK段丢失了,客户端也开始重新发送。

客户端重新发送过程将在第1.1节中介绍。 服务端的SYN ACK重发次数由参数tcp_synack_retries设置。

1.1 .第三次握手协议丢失。 (ACK )客户端从服务器端接收到第二个握手SYN ACK消息段后,将TCP状态置于ESTABLISH状态,并将ACK消息段发送到服务器端。

如果第三次握手的ACK段丢失,服务器将重新发送SYN ACK段,直到接收到ACK响应或达到最大重发次数。

重传周期:

如果ACK完全丢失,则客户端的TCP状态为ESTABLISH,服务端的TCP状态为SYN_RCVD。 此时,如果从客户端收到TCP数据,则为:

1.2次挥手过程信息丢失:正常4次挥手过程:

1.2.1如果丢失了第一个挥手消息(FIN ),则在客户端(活动闭合器)调用close )函数时,将向服务端发送FIN消息(确切地说,调用close时,软盘的引用数减少1 )

当第一个挥手的FIN分段丢失时,客户端启动重传过程,重传次数由内核参数tcp_orphan_retries控制。

注意: 第三次握手的ACK报文段没有重传,当ACK丢失,只能依靠服务端重传SYN+ACK报文段。

1.2.2第二次挥手消息丢失时(ACK )服务端收到第一次挥手FIN消息段后,将本地TCP状态设置为CLOSE_WAIT,将第二次挥手的ACK消息段设置为

如上所述,当第一次挥手的FIN报文段达到最大重传次数后,客户端将停止重传,直接进入 CLOSE 状态。,因此如果ACK丢失,客户端将在收到ACK消息或达到FIN最大重发次数之前重发FIN消息。

还有一点需要注意:

如果客户端成功接收到第二次挥手的ACK消息,则客户端的TCP状态设置为FIN_WAIT_2,客户端开始等待服务端第三次挥手的FIN消息。

FIN_WAIT_2的状态不会持续很久。 内核参数tcp_fin_timeout控制时间,默认值为60秒。

ACK报文段是不会重传的

trong>

1.2.3 第三次挥手消息丢失:(FIN)

当服务端收到客户端的第二次挥手的FIN报文后,内核会自动的回复ACK,并置TCP状态为 CLOSE_WAIT,顾名思义,CLOSE_WAIT状态表示内核在等待应用进程调用clsoe()函数关闭连接(wait to close)。

此时,内核没有权利替代进程关闭连接,必须由进程主动调用close函数来触发服务端发送FIN报文。

当服务端调用close()函数后,TCP状态将从 CLOSE_WAIT 状态转入 LAST_ACK 状态,如果在超时时间内未收到客户端的第四次挥手 ACK报文,则重传FIN报文,最大重传次数由内核参数 tcp_orphan_retries 控制。

CLOSE_WAIT状态的最大持续时间是多少:
CLOSE_WAIT状态表示的就是内核在等待应用进程调用close()函数来关闭连接,至于应用进程什么时候close,这完全取决于程序。所以,从理论上来讲,只要被动关闭端不断电,进程不退出,那么CLOSE_WAIT状态就会一直持续下午,CLOSE_WAIT的最大持续时间从理论上来讲可以达到无限长

1.2.4 第四次挥手消息丢失:(ACK)

当客户端收到服务端的第三次挥手FIN报文后,TCP状态由 FIN_WAIT_2 转入 TIME_WAIT,并回复第四次挥手ACK报文给服务端。

如果第四次挥手ACK报文丢失,ACK报文不会重传,服务端在超时未收到ACK后会重传FIN,直至成功收到ACK会达到最大重传次数。

TIME_WAIT的最大持续时间默认为 60秒(2*MSL),超时后TCP状态转为 CLOSED。


2. 尝试连接IP不存在或端口存在的目的主机: 2.1 结论: 2.1.1 当试图连接一个IP不存在的主机时: 如果尝试连接的IP在局域网内,则会发送N次ARP请求,向局域网内请求获取目的主机的MAC地址,且本地主机不能发出TCP握手消息;如果尝试连接的IP在局域网外,则会将TCP握手消息通过网关路由发出到局域网外,但因为最终找不到目的地,会触发TCP的超时重传,直至达到最大重传次数后关闭TCP连接。 2.1.2 当试图连接一个IP存在但端口不存在的主机时: 不论尝试连接的主机是在局域网内还是局域网外,当目的主机收到源主机的TCP握手消息后,判断这个端口上并没有应用进程,内核协议栈会立即回复RST复位报文段,发送端在收到RST后关闭TCP连接。如果目的主机设置了防火墙策略,限制他人将消息发送到不对外暴露的端口,那么这种情况目的主机会将收到的TCP握手消息直接丢弃,源主机在超时后进行重传,直至达到最大重传次数后关闭TCP连接。
2.2 原理: 为什么在连接局域网内不存在的IP时会一直重发ARP请求,而没有发出SYN报文:
  当连接一个局域网内的IP时,主机会先到本地ARP表中查询是否有目的IP的MAC地址,如有则返回,如没有则向局域网广播一条ARP请求,请求获取目的IP的MAC地址。
  当局域网内的其他主机收到ARP请求后,判断请求中的IP是否为自己的IP,如果是则向请求方发送ARQ响应,捎带上自己的MAC地址;如果不是自己的IP则直接将收到的ARP请求丢弃。
  当源主机在本地的ARP表中没有找到与目的IP一致的缓存记录时,此时会将SYN报文放进 unresolved_queue 队列中缓存起来,直至收到有效的ARP响应后,才会将SYN报文从缓存去列中取出并打上MAC头发给目的主机。如果始终得不到ARP响应,则SYN握手消息将一直不会发出。
  注意 ARP协议本身是没有重传机制的,之所以会重复发送ARP请求,是因为触发了TCP三次握手的重传机制,而每一次重传SYN都会对应的向局域网内发出一条ARP请求。RST报文:
  TCP正常情况下断开连接是用四次挥手,这是正常时候的优雅做法。但异常情况下,收发双方因为某种异常情况无法完成四次挥手,所以就需要一个机制来强行关闭连接。
  RST就是用于这种情况,一般用来异常的关闭一条连接。 通过在TCP头中将 RST标志位置为1,在接收端收到后就会关闭连接,此时一般会看到 “connection reset” 或 “connection refused” 的报错。
3. 在连接状态下的进程/主机异常宕机: 3.1 没有开启keepalive选项,且没有数据交互的情况:

一道面试题:
一个TCP连接,没有打开keepalive选项,没有数据交互,现在一端突然掉电和一端的进程crash了,请问这两种情况有什么区别?

第一种情况:主机掉电:
对端主机崩溃对于服务端而言是无法感知的 ,此时又没有开启keepalive,又没有数据交互,则服务端的tcp连接会一直处于 ESTABLISHED 连接状态,直到服务端重启进程。第二种情况:主机正常,网络进程crash:
即使是在没有开启keepalive,且没有数据交互的情况下,如果其中一方的进程发生了崩溃,这个过程操作系统是可以感知的到的,于是就会 发送FIN报文给对端,双方进行TCP四次挥手关闭连接。
注意:在进程异常crash时,系统在检测到进程crash后会发送FIN给对端,注意这里发送的 FIN,走正常的四次挥手关闭流程,不是发送RST直接复位连接。
3.2 没有开启keepalive选项,但有数据交互的情况:

(1)如果是主机正常,网络进程crash,无论是否有数据交互,处理方式都是一样的,即发生进程crash一端的主机系统发送FIN报文,进行TCP四次挥手流程关闭连接。

(2)如果是主机异常宕机,此时可细分为两种情况:

客户端主机宕机,又迅速重启;客户端主机宕机,一直没有重启。

在客户端主机宕机后,服务端向客户端发送的业务数据报文会得不到ACK响应,在一定时长后,服务端会触发 超时重传 机制,重传未被响应的业务数据报文。

如果在服务端重传业务数据的过程中,客户端的主机重启完成,此时如果客户端的网络进程没有重启,则客户端主机收到服务端的业务数据后判断没有进程监听这个端口,会向服务端回复RST报文重置连接;如果客户端迅速重启,且主机上有新的进程重新绑定了这个端口,这种情况应该相当于新连接上收到旧连接的报文来处理?如果客户端主机宕机后,一直没有重启,则服务端的重传报文达到一定阈值后,内核就会判断这条tcp连接出现问题,然后通知应用进程连接不可用(send返回-1 ?)

tcp_retries2:

在Linux系统中,通过 tcp_retries2 配置参数控制报文的最大重传次数,默认值为15,每次重传的时间以指数退避的方式计算。当达到最大重传次数后,tcp就会停止重传。


3.3 已开启keepalive选项的情况:

TCP的keepalive保活机制默认是关闭的,要想使用,必须通过设置套接字选项的方式手动开启:

bool bKeepAlive = TRUE;int nRet = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char*)&bKeepAlive, sizeof(bKeepAlive));if(nRet == SOCKET_ERROR) { return FALSE;}

关于keepalive机制的默认配置:

net.ipv4.tcp_keepalive_time = 7200net.ipv4.tcp_keepalive_intvl = 75net.ipv4.tcp_keepalive_probes = 9

如果一条tcp连接在连续7200秒的时间内(2小时)都没有数据报文,则会触发保活检测,每次发送探测报文的时间间隔是75秒,最多发送9轮。
所以最大时间是:
7200 + 75*9 = 2小时11分15秒

保活机制的探测结果有三种情况:

对端程序正常运行,且中间网络通畅,此时keepalive探测报文能够顺利到达对端,对端在收到报文后回复ACK,重置tcp保活时间;对端主机正常,但网络进程崩溃 (正常情况下发生这种问题时,对端主机的操作系统内核能够检测到网络进程崩溃,此时内核会自动发起四次挥手关闭连接,但是如果FIN报文段丢失并,在达到FIN最大重传次数后TCP进入CLOSED状态,就需要依赖keepalive保活机制了),在对端主机收到keepalive检测报文后,判断目的端口没有应用进程监听,则回复一条RST报文关闭tcp连接;对端主机宕机,且未重启,中间网络正常,对端主机崩溃对于服务端来说是无法感知的,此时发送的keepalive报文石沉大海,没有主机对其响应,需要达到最大检测次数后关闭连接;对端主机宕机,并已重启,不论网络进程是否重启,在收到keepalive检测报文后,回复RST重置连接;中间网络出现问题,这种情况下无论对端主机、网络进程是否正常,keepalive报文都不可达,需要等待达到最大检测次数后关闭tcp连接。

对于正常四次挥手关闭,tcp在收到FIN报文后,会返回可读事件,应用程序调用read后返回0,说明对方已经close;

对于keepalive超时的情况,当tcp检测到对端已不可达,会返回一个可读事件,应用程序调用recv会返回-1,errno被置为 ETIMEOUT,方便应用程序及时清理不可用的连接。

参考内容:

https://blog.csdn.net/ilini/article/details/118565606
https://zhuanlan.zhihu.com/p/390939380
https://blog.csdn.net/tdy353021560/article/details/38368845

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。