2014-01-27 207 views
2

由於它在維基百科上撰寫關閉TCP連接應該使用數據包FIN - >(FIN,ACK) - > ACK。但是,當我使用close()函數關閉套接字時,我看不到FIN數據包,從服務器到客戶端立即發送(FIN,ACK)數據包,然後客戶端通過發送(FIN,ACK)關閉連接,服務器響應ACK分組。那麼丟失的FIN數據包在哪裏(也許它合併到FIN,ACK)?FIN省略,FIN-ACK發送

+0

您確定服務器之前沒有關閉連接嗎?它看起來像服務器關閉連接 – hek2mgl

+0

我沒有看到這樣的過渡:http://blog.zhuzhaoyuan.com/wp-content/uploads/2009/03/tcp-states1.png 創建一個最小的tcpdump示例。 –

+0

當我使用close()函數關閉套接字時,我發現客戶端發送FIN,ACK,然後服務器以ACK響應 – scdmb

回答

6

收盤順序也可以是不同的,並不需要有相同的包內FIN + ACK:

  • ACK只是確認收到的數據(例如,接受一切都交給給出序列號)
  • 數據包將重新發送,直到收到一個ACK爲止
  • FIN只是說發送FIN的端不會再發送任何數據。它不會提供任何信息,如果它仍然會收到數據。
  • 像其他分組FIN將被重新發送,直到接收被確認

協議(如HTTP)支持單面關機,例如客戶端發送請求數據,然後發送FIN以通知服務器,它不會再發送數據。但它仍然會收到服務器發送的數據。服務器將像以前對所有數據所做的那樣承認FIN。一旦服務器完成,它將發送它自己的客戶端確認的FIN。在這種情況下,您有

1. client: FIN (will not send more) 
2. server: ACK (received the FIN) 
.. server: sends more data..., client ACKs these data 
3. server: FIN (will not send more) 
4. client: ACK (received the FIN) 

請注意,您在步驟#1中看到的數據包可能也有一個ACK。但是這個ACK只是確認服務器之前發送的數據。如果服務器沒有更多的數據要發送,它可能會關閉連接。在這種情況下,步驟2 + 3可以合併,例如,服務器發送FIN + ACK,其中ACK確認客戶端收到的FIN。

如果一方發送它的FIN,則連接稱爲半封閉。一旦雙方發送它們的FIN並接收到FIN的ACK,無論它們是以3或4個數據包的形式進行傳輸,它都會被完全關閉。

+0

+1理解「ACK」的關鍵是它將**應用於指定的確認號碼**。 'FIN' +'ACK'不是特殊**,除非**確認號碼是_lastdatabyte + 1_(因爲'FIN'按順序號計數,就像'SYN'一樣)。 –

+0

我猜RFC1122第4.2.3.2節是關鍵。我錯了嗎? – hek2mgl

+0

不是。這涉及延遲ACK等優化。關鍵是RFC793(例如RFC for TCP)部分3.5。但RFC不是一個容易閱讀:) –

0

您必須已經收到FIN才能發送FIN/ACK。您是否因閱讀EOS而關閉?

+0

我也這麼認爲,因爲它在文檔中。但你可以嘗試使用telnet和wireshark。客戶端真正發送'FIN,ACK'。然後服務器發送'FIN,ACK',最後客戶端發送'ACK'。在Linux 3.2上觀察到 – hek2mgl

+0

看起來好像有點可選,因爲服務器只檢查'FIN '設置。但是,我想這仍然有意義:) – hek2mgl

+0

不,它不是'可選的',它是RFC 793要求的。你能回答我的問題嗎? – EJP