2013-10-29 49 views
0

我知道,如果遠程主機正常關閉連接,epoll將報告EPOLLIN,並呼籲readrecv不會阻止,並會返回0字節(即結束流)。什麼是「可讀」(的kqueue/epoll的)

然而,如果連接沒有正常關閉,和一個或writesend操作失敗,這是否導致epoll隨後返回EPOLLIN該插座,產生流場景的相同/相似端?

我試圖找到關於這種行爲的文檔,但都沒有成功,而我可以測試它,我不感興趣,在與特定的內核版本特定的分佈會發生什麼。

回答

-1

當對等機器意外關閉時,它不會返回EPOLLIN。在過去,我中遇到這種現象通過VirtualBox的操作步驟如下:在一個VM

  1. 啓動服務器。
  2. 在其他虛擬機上啓動客戶端,連接服務器並保持連接而不做任何事情。
  3. 保存客戶端VM狀態(類似於休眠)。

我看見的連接仍然被

netstat -anp --tcp 

換句話說成立於服務器VM,EPOLLIN不是在服務器觸發。

http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/說會在默認情況下保持7200秒。

當然,你可以更改setsockopt的或內核參數保持活動超時值。

但是有些書說更好的解決方案是在應用程序層檢測它,設計協議,確保定期發送一些虛擬消息來檢測連接狀態。

+0

雖然我的問題更具體。如果連接如您的示例中那樣關閉,然後寫入失敗,那麼現在知道管道已損壞,EPOLLIN會返回。 –

-1

epoll()基本上是poll()但是當你增加的fd數量也能更好地伸縮。我不確定它在將它用作邊緣觸發界面時的功能。但對於電平觸發 - 是的,它總是返回EPOLLIN,假設你正在監聽這個事件,如果流的末尾被檢測到。

雖然你必須知道TCP是不完美的。如果連接異常終止(physycal連接斷開),則在您寫入套接字之前,您的一方可能永遠無法檢測到該事件。 TCP_KEEPALIVE可能會有幫助,但不是很多。

+0

他不是在問流結束。他在問關於一個不正常的關閉連接。 – EJP

+0

@EJP,請告訴我什麼是差異?沒有「連接悶悶不樂」的東西。更高層次的協議決定了這些事情 – GreenScape

2

這的確不是從規格完全明顯,但它的工作原理爲poll()如下:

  • 如果有可用於讀取數據,即使連接被關閉,POLLIN返回。
  • 如果沒有讀或寫是因爲在關閉的連接的可能,POLLHUPPOLLERR返回。
  • 如果讀數不再可能,但寫入是(例如,如果另一方做了shutdown(SHUT_WR)),則返回POLLIN,並且不返回POLLHUPPOLLERR。 (這允許等待POLLOUT正常。)

簡單的事情是當任何POLLINPOLLHUPPOLLERR設置爲嘗試讀取。

kqueue(),也僅僅是一個EVFILT_READ過濾器可能被觸發。這在手冊頁中有描述,應該足夠清楚。

請注意,如果您不啓用TCP keepalive(FreeBSD默認啓用它,但大多數其他操作系統不啓用),如果網絡以某種方式中斷,等待數據讀取可能會永久停止。即使TCP keepalive處於打開狀態,通常也需要幾個小時才能檢測到連接斷開。

+0

點2與點3不一致。TCP無法區分傳入的關閉和傳入的SHUT_WR。兩者都是FIN,因此都必須生產EPOLLIN。 – EJP

+1

@EJP TCP可以區別對方在執行'SHUT_WR'的同時仍然讀取數據,並且發現錯誤,例如超時或RST設置的數據包阻止讀取和寫入。然而,'close'出現在另一端,就像'SHUT_WR'一樣,直到試圖發送數據,'SHUT_RD'只在它試圖發送數據時影響另一端。 – jilles

-1

但是,如果連接沒有正常關閉,並且寫入或發送操作失敗,這是否會導致epoll隨後返回該套接字的EPOLLIN,從而產生相同/相似的流結束方案?

不。這意味着收到FIN,這意味着正常終止連接,但沒有發生。我希望你會得到一個EPOLLERR或EPOLLHUP。

但我很好奇,爲什麼你會不會已經在得到寫入錯誤關閉套接字,爲什麼你還是會投票吧。這不是正確的行爲。

+1

我想確保讀取套接字上可用的所有數據。如果我在寫入錯誤時終止套接字,連接終止時是不可能的,還有數據要讀取? –