簡體   English   中英

Python - 在 TCP RST 之后從套接字讀取剩余數據

[英]Python - Read remaining data from socket after TCP RST

我正在使用以下用例實現文件傳輸協議:

  • 服務器在幾個幀內逐塊發送文件。
  • 客戶端可能會取消傳輸:為此,它會發送一條消息並在 TCP 級別斷開連接。

在這種情況下,在服務器端(在 Windows 上運行的 Python)發生的事情是我在將數據發送到客戶端時捕獲了 ConnectionResetException(這是正常的,客戶端已斷開套接字)。 我想讀取客戶端發送的最新數據(用於中止調用的消息),但調用 mysocket.recv() 仍然會引發 ConnectionResetException。

通過wireshark 捕獲,我可以清楚地看到消息是在TCP 斷開之前由客戶端正確發送的。

有什么想法嗎? 謝謝!

虛擬現實

為了了解如何處理這種情況,您需要了解 TCP 連接是如何關閉的(參見,例如this )以及套接字 API 如何與干凈關閉相關(沒有失敗,參見this )。

您的客戶端很可能會調用 close 來終止連接。 這樣做的問題是,套接字接收隊列中可能有未讀數據或從另一端很快到達的數據,您將無法再讀取,這基本上是一種錯誤情況。 為了向另一端發出無法將發送的數據傳遞給接收應用程序的信號,發送復位(從技術上講,根據 RFC,“應該發送”)並且 TCP 連接異常終止。

您可能認為啟用 SO_LINGER 會有所幫助(很多很多位已經溢出,所以我不會進一步詳細說明),但它不會解決客戶端未讀取數據導致重置的問題。

客戶端需要改為調用shutdown(SHUT_WR)來指示它已完成發送,然后繼續調用recv()直到它讀取到0 字節指示另一端已完成發送。 然后您可以調用close()

請注意,Python 2 插槽文檔指出

根據平台,關閉連接的一半也可以關閉另一半(例如,在 Mac OS X 上,shutdown(SHUT_WR) 不允許在連接的另一端進行進一步讀取)。

這對我來說聽起來像是一個錯誤。 為了解決這個問題,您必須發送您的取消消息,然后繼續閱讀,直到您獲得 0 個字節,以便您知道服務器收到了取消消息。 然后您可以close套接字。

Python 3.8 文檔沒有做出這樣的免責聲明。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM