2014-02-11 24 views
1

我有一个使用TCP套接字在C编写的客户端/服务器应用程序。我想通过在客户端套接字上启用SO_KEEPALIVE选项来了解已故的服务器进程。我正在使用Linux。在Linux上默认启用SO_KEEPALIVE行为?

我将默认时间从2小时修改为10分钟。

echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time 

我使用setsockopt()在客户端套接字上启用了SO_KEEPALIVE。我故意杀死(kill -9)服务器进程,同时它将数据发送到客户端。如预期的那样,在10分钟超时(加上探针的额外时间)后,客户端套接字得到通知(读取(scoket,...)返回0)。但是,令我惊讶的是,即使我在客户端套接字上禁用此选项,在指定的超时后(read()返回零)仍然会收到通知。

在Linux中默认启用了这种行为吗?

此外,我觉得read()返回零是不合适的,不应该读取()时返回一些错误,当对端死亡?

回答

2

Keepalive导致连接重置。唯一导致read()返回零的是接收FIN。 Ergo,你收到了一个FIN,而不是一个Keepalive终止,并且这并不表明在Linux中默认启用了Keepalive。这将违反RFC 1122.

+0

感谢您的信息。假设Keepalive在默认情况下或者我的更改未启用。但是我杀了服务器进程。客户如何在一段时间后收到FIN? – ernesto

+0

没关系。我杀死了服务器进程,但它有一个sleep()调用,它似乎被催生为另一个进程......并仍在与客户端进行通信。谢谢。 – ernesto

+1

但还有其他的东西......如果我突然杀死服务器进程(和关联的子进程),read()也会返回零。基本上,客户端在select()调用中等待客户端套接字准备好读取时通知....当我杀死服务器时,它立即得到通知,并且read()返回零。为什么这样?我突然杀死了服务器,在服务器中没有调用close()或shutdown()函数,然后谁发送了FIN数据包给客户端? – ernesto