[英]Can we just reset TCP connections after an application level acknowledgement has been received?
我正在研究重置TCP連接,以解決TIME_WAIT
問題。
讓我們以下面的請求-應答協議為例:
這會在服務器上導致TIME_WAIT
狀態。 作為一種變化,客戶可以先關閉。 然后, TIME_WAIT
到達客戶端。
我們不能用以下內容代替步驟4和5嗎?
這似乎是避免TIME_WAIT
問題的一種方法。 服務器已通過發送答復來證明已接收並處理了請求。 客戶收到回復后,連接將消耗大量資源,並且可以斷開連接。
這是一個好主意嗎?
唯一的問題是服務器不知道客戶端是否收到了所有內容。 情況是模棱兩可的:客戶端連接是由於客戶端收到了整個答復而重置的,還是由於其他原因而重置了?
添加應用程序級別的確認不能可靠地解決問題。 如果客戶端確認,然后立即中止關閉,則客戶端不能確定服務器是否收到該確認,因為中止關閉會丟棄未傳輸的數據。 而且,即使數據被發送,由於連接不可靠,它也可能丟失。 並且一旦連接中止,TCP堆棧將不再提供該數據的重傳。
正常的,非繁瑣的情況通過讓客戶端和服務器TCP堆棧獨立於應用程序執行來照顧最終儀式來解決該問題。
因此,總而言之,如果我們關心的只是客戶端收到其答復,並且服務器不關心該請求是否成功,則中止是可以的:在許多情況下這不是不合理的假設。
我懷疑您對服務器上的TIME_WAIT錯誤。
如果對單個基於TCP的客戶端-服務器事務遵循以下順序,則TIME_WAIT在客戶端:
客戶端啟動與服務器的活動連接
客戶端向服務器發送請求。
客戶端半關閉連接(即發送FIN)
服務器讀取客戶端請求,直到EOF(FIN段)
服務器發送答復並關閉(生成FIN)
客戶閱讀對EOF的回復
客戶關閉。
由於客戶端是第一個發送FIN的用戶,因此進入TIME_WAIT。
訣竅是,客戶端必須首先關閉發送方向,然后服務器通過讀取整個請求來對其進行同步。 換句話說,您將流邊界用作消息邊界。
您要嘗試做的是純粹在應用程序協議內部進行請求框架,而根本不使用TCP框架。 也就是說,服務器在客戶端未關閉的情況下識別出客戶端消息的結尾,同樣,客戶端在不關心讀取到結尾的情況下解析服務器響應。
即使您的協議是這樣的,您仍然可以進行半關閉舞蹈程序的動作。 服務器在檢索到客戶端請求之后,仍然可以繼續從其套接字讀取並丟棄字節,直到讀取所有內容為止,即使不需要字節也是如此。
我會說:不,這不是一個好主意。 每種可能的解決方案都以TIME_WAIT
最終解決的相同“問題”結束:甲方如何確認連接的結束(或確認另一方對連接結束的最終確認),知道乙方得到了確認? 答案總是:它不可能永遠知道這一點。
你說:
服務器通過發送答復來證明它已接收並處理了請求
...但是如果該回復丟失了怎么辦? 服務器現在已經清理了會話的那一部分,但是客戶端將永遠等待該回復。
乍一看,TCP狀態機可能看起來過於復雜,但是這樣做的確有充分的理由。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.