2012-09-04 19 views
7

我正在通過TCP套接字測試客戶端 - 服務器通信。我用C編寫了服務器,並且正在Linux機器上運行它,我使用nc作爲測試客戶端。斷開的管道僅在第二次發送時關閉套接字

服務器在與客戶端初始交換消息後,定期向客戶端發送一些 消息,但沒有得到任何響應。

如果我殺了客戶端,我希望由服務器完成的第一send()失敗 EPIPE錯誤,但這個僅在第二send()客戶端已經經過證明! 我殺了客戶端後第一個send()能夠成功發送1100個字節到(我想是封閉的)套接字。以下send()操作以EPIPE結束。

有人能解釋我這種行爲嗎? 這是因爲我寫入TCP/IP協議棧,因此它可以在堆棧 發送時發送? 如果是這樣,我該如何檢查連接狀態?可以肯定的是對方還在那裏。

回答

4

正常TCP連接是一種四方握手。

http://en.wikipedia.org/wiki/Transmission_Control_Protocol

當你殺FIN段被從客戶端發送到服務器和服務器協議棧中的客戶端發送ACK

在這裏,如果服務器試圖讀取數據,讀取調用將返回值爲0,所以您的服務器程序可以明白對方已關閉,並在此之後通常會關閉連接套接字。這將允許從服務器端發送來自服務器端的FIN,並且在從客戶端接收到最後的ACK之後,正常的4次握手將完成。

(PL讀Q的http://www.faqs.org/faqs/unix-faq/socket/ 2.1)

但在這裏,你從服務器寫入數據,因此服務器只發送數據後得到一個RESET從客戶端。因此,您在第二次發送的第一次發送操作後收到錯誤。

因此,嘗試關閉連接從客戶端突然而不是4方式handsaking,通過設置 逗號選項和超時爲0,以便您可以得到一個錯誤(可能不同於EPIPE)在第一次調用發送服務器端。(這不是一個recommnended的做法,但只有你在這種特殊情況下理解)

Try the following option of nc, nc -L 0 to set the linger option and timeout to 0 

(我沒有嘗試過的nc此選項,PL。在這個環節檢查細節http://docs.oracle.com/cd/E23824_01/html/821-1461/nc-1.html

來自上述網站的nc示例,

Connect to TCP port, send some data and terminate the connection with 
TCP RST segment 
(instead of classic TCP closing handshake) by setting the linger option and 
timeout to 0: 

$ echo "foo" | nc -L 0 host.example.com 22 
+0

感謝您的回答,細緻而清晰。不幸的是,我無法測試你建議我的nc選項,因爲我的Linux機器上的命令似乎不支持它。順便說一句,你指給我的文件和你給我的解釋清楚而有用。謝謝! – Igor

相關問題