2011-06-04 126 views
2

我已經寫在C AF_INET/SOCK_STREAM服務器上的Android/Linux上運行,看起來更礦石較少這樣後立即:「連接重置」如果服務器調用close()寫()

... 
for (;;) { 
    client = accept(...); 
    read(client, &message, sizeof(message)); 
    response = process(&message); 
    write(client, response, sizeof(*response)); 
    close(client); 
} 

據我所知,關閉調用不應立即終止與客戶端的連接,但它顯然確實如此:客戶端在有機會讀取服務器的響應之前報告「連接重置」。

如果我在write()close()之間插入延遲,客戶端可以按預期讀取響應。

我得到了一個暗示,它可能與SO_LINGER選項做的,但我檢查了它的價值和struct苟延殘喘的成員(l_onoffl_linger)具有零值。

任何想法?

回答

3

Stevens描述了這種情況可能發生的配置,但它取決於服務器在調用close()(客戶端應該「知道」連接正在關閉後)後發送更多數據的客戶端。 UNP 2nd ed s5.12。

嘗試tcpdumping對話以找出真正發生的事情。如果兩個端點之間存在「聰明」的網關(例如NAT),tcpdump都會結束並尋找差異。

+0

我懷疑這是發生了什麼事。 +1來捕捉這種可能性,並就如何調試情況提供很好的建議。 – 2012-05-22 14:44:49

0

如果您希望在關閉前發送排隊數據,應設置SO_LINGER(即設置爲1而不是0)。

SO_LINGER 如果數據存在,則關閉()的延續。此選項控制 在未發送消息 在套接字上排隊時執行的操作,並且執行close()時爲 。如果SO_LINGER被設置, 系統將在關閉()期間阻塞調用線程 ,直到它可以傳輸數據或者直到時間到期。如果 SO_LINGER未指定,並且發出 close(),則系統會以允許 調用線程儘可能快地繼續 的方式處理 。此選項採用 掛鉤結構(如 標頭中所定義)來指定 狀態的選項並延續 區間。

+0

這應該不會影響客戶端/網絡,只是在流連忘返的時候讓服務器阻止而不是繼續。 – 2012-05-22 14:44:15

1

當您撥打close()與發送的數據連接時,連接將重置。特別是對於這種情況,使用帶有SHUT_WR標誌的shutdown()的序列,然後使用阻止read()

關閉套接字的寫入結束會立即發送FIN並立即返回,並且一旦對等體以FIN響應,所述read()將阻塞並返回0。基本上,這是你所需要的,以代替你正在談論的write()close()之間的延遲。

在這種情況下,您不需要使用linger選項執行任何操作,將所有選項都保留爲默認值。

相關問題