2014-02-11 23 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