TCP服务器如何处理死掉的连接
互联网公司的TCP服务器(以下简称server)通常需要处理大量的来自TCP客户端(以下简称client)的连接,连接必然会占用系统资源(不过对于多路复用的模型来说,实际上只占用了一个文件描述符和少量内存)。在client断开连接、client进程退出、client主机正常关机、client主机崩溃的情况下,server如何处理这些连接?
一、client断开连接、client进程崩溃、client主机正常关机
1.client断开连接。即client主动调用close断开连接
2.client进程退出(包括正常退出和进程崩溃)。当进程退出时,操作系统会主动帮进程关闭所有打开的文件描述符
3.client主机正常关机。Unix系统关机时,init进程会给所有进程发送SIGTERM信号,给进程一段时间来清除和终止。然后发送SIGKILL信号来强行中止进程。无论进程如何终止,所有的文件描述符都会被关闭
所以这三种情况都会调用close来关闭,进入正常的TCP连接关闭流程。
二、client主机崩溃
主机崩溃是指client主机直接停掉,不能做任何处理,比如直接断电或者断网。这种情况下路由根本找不到该IP,服务端也收不到来自client的FIN。那server要如何处理? 这个问题分两种情况:
1.如果断开后,server调用send向client发送数据
send会立刻完成,因为send只是把数据写入内核。TCP会持续重传数据分节,n分钟后放弃重传,这时候server进程就知道连接已经坏了,那么在这个socket上的操作都会返回错误。
2.如果断开后,server再也没有调用send,而是在recv数据
这时候就尴尬了,如果不做额外的处理,recv会一直阻塞。这时候就需要利用SO_KEEPALIVE套接字选项或应用层的心跳来解决这个问题。
参考文献
UNIX网络编程 卷1:套接字联网API(第三版)5.12~5.16