大家好,欢迎来到IT知识分享网。
如何及时有效地检测到一方的非正常断开,一直有两种技术可以运用。一种是由TCP协议层实现的Keepalive,另一种是由应用层自己实现的心跳包。TCP默认并不开启Keepalive功能,因为开启Keepalive功能需要消耗额外的宽带和流量
一。服务器进程终止:
建立连接以后用kill杀死服务器进程,作为进程终止处理的部分工作,子进程中所有打开着的描述字都被关闭。这就导致向客户发送一个FIN,而客户TCP则响应以一个ACK。这就是TCP连接终止的前一半工作。
此时客户端进程处于FIN_WAIT2状态,客户端处于CLOSE_WAIT状态。当客户端再向服务器发送数据时,由于服务器打开的套接字端口已经终止,则响应一个RST给客户端。
二。 服务器主机崩溃:
1:当服务器主机崩溃时,已有的网络连接上发不出任何东西。这里我们假设的是主机崩溃,而不是执行了关机命令。
2:我们在客户上输入一行文本,它由write写入内核,再由客户TCP作为一个数据分节送出。客户随后阻塞于read调用,等待服务器的应答。
3:这种情况下,客户TCP持续重传数据分节,试图从服务器上接受一个ACK。(源自Berkeley的实现重传该数据分节12次,共等待约9分钟才放弃重传。)当客户TCP最终放弃时(假设这段时间内,服务器主机没有重新启动或者如果是服务器主机为崩溃但从网络上不可达的情况,那么假设主机仍然不可达),返回客户进程一个错误。既然客户阻塞在readline调用上,该调用将返回一个错误。假设服务器已崩溃,从而对客户的数据分节根本没有响应,那么所返回的错误是ETIMEDOUT。然而如果某个中间路由器判定服务器主机已不可达,从而响应以一个“destination unreachable”,那么所返回的错误是EHOSTUNREACH或ENETUNREACH。
另外我们刚讨论的情形只有在向服务器主机发送数据时,才能检测出它已经崩溃,如果我们不主动发送主句也想检测出服务器主机的崩溃,那么就需要用到SO_KEEPALIVE这个套接口选项。
SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:对方接收一切正常:以期望的ACK响应。2小时后,TCP将发出另一个探测分节。对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。
三、服务器主机崩溃后重启
在前一节的分析中,当我们发送数据时,服务器主机仍然处于崩溃状态;这节,我们将在发送数据前重新启动崩溃了的服务器主机。模拟这种情况的简单方法就是:建立连接,再从网络上端口服务器主机,将它关机后再重启,最后把它重新连接到网络中。
当服务器主机崩溃后重启时,它的TCP丢失了崩溃前的所有连接信息,因此服务器TCP对于所收到的来自客户的数据分节响应以一个RST。当客户TCP收到该RST时,客户正阻塞于read调用,导致该调用返回ECONNRESET错误。
四、服务器主机关机
Unix系统关机时,init进程通常先给所有进程发送SIGTERM信号(该信号可被捕获),再等待一段固定的时间(一般在5~20秒之间),然后给所有仍在运行的进程发送SIGKILL信号(该信号不能被捕获)。这么做是留给所有运行中的进程一小段时间来清除和终止。如果我们不捕获SIGTERM信号并终止,我们的服务器将由SIGKILL信号终止。当服务器进程终止时,它的所有打开着的描述字都被关闭,随后发生的步骤与第一节中讨论过的一样。正如第一节中所述的情形,我们必须在客户中使用select或poll函数,使得服务器进程的终止已经发生,客户马上检测到。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/22550.html