3 回答

TA貢獻1828條經(jīng)驗 獲得超13個贊
現(xiàn)有的答案都不告訴人們?nèi)绾?code>shutdown以及close
在TCP協(xié)議級別的作品,所以它是值得添加此。
標準TCP連接通過4路終結(jié)終止:
一旦參與者沒有更多數(shù)據(jù)要發(fā)送,它就會向另一個發(fā)送FIN數(shù)據(jù)包
另一方返回FIN的ACK。
當另一方也完成數(shù)據(jù)傳輸時,它會發(fā)送另一個FIN數(shù)據(jù)包
初始參與者返回ACK并完成傳輸。
但是,還有另一種“緊急”方式來關(guān)閉TCP連接:
參與者發(fā)送RST數(shù)據(jù)包并放棄連接
另一方收到一個RST,然后放棄連接
在我使用Wireshark進行的測試中,使用默認套接字選項,shutdown
將FIN數(shù)據(jù)包發(fā)送到另一端,但確實如此。在另一方向您發(fā)送FIN數(shù)據(jù)包之前,您仍然可以接收數(shù)據(jù)。一旦發(fā)生這種情況,您Receive
將獲得0大小的結(jié)果。因此,如果您是第一個關(guān)閉“發(fā)送”的人,則應在完成數(shù)據(jù)接收后關(guān)閉套接字。
另一方面,如果close
在連接仍處于活動狀態(tài)時進行呼叫(另一方仍處于活動狀態(tài),并且系統(tǒng)緩沖區(qū)中可能還有未發(fā)送的數(shù)據(jù)),則會將RST數(shù)據(jù)包發(fā)送到另一端。這有利于錯誤。例如,如果您認為對方提供了錯誤的數(shù)據(jù)或拒絕提供數(shù)據(jù)(DOS攻擊?),您可以立即關(guān)閉套接字。
我對規(guī)則的看法是:
考慮
shutdown
之前close
可能當如果在決定關(guān)閉之前完成了接收(接收的0大小數(shù)據(jù)),請在最后一次發(fā)送(如果有)完成后關(guān)閉連接。
如果要正常關(guān)閉連接,請關(guān)閉連接(使用SHUT_WR,如果您不關(guān)心在此之后接收數(shù)據(jù),也使用SHUT_RD),并等待直到收到0大小的數(shù)據(jù),然后關(guān)閉插座。
在任何情況下,如果發(fā)生任何其他錯誤(例如超時),只需關(guān)閉套接字即可。
SHUT_RD和SHUT_WR的理想實現(xiàn)
以下未經(jīng)過測試,信任風險自負。但是,我相信這是一種合理而實用的做事方式。
如果TCP堆棧僅通過SHUT_RD接收關(guān)閉,則應將此連接標記為不再需要數(shù)據(jù)。任何掛起和后續(xù)read
請求(無論它們處于哪個線程)都將返回零大小的結(jié)果。但是,連接仍然是活動的和可用的 - 例如,您仍然可以接收OOB數(shù)據(jù)。此外,操作系統(tǒng)將刪除它為此連接接收的任何數(shù)據(jù)。但就是這樣,沒有包裹會被發(fā)送到另一方。
如果TCP堆棧僅通過SHUT_WR接收關(guān)閉,則應標記此連接,因為不能再發(fā)送數(shù)據(jù)。所有掛起的寫入請求都將完成,但后續(xù)寫入請求將失敗。此外,F(xiàn)IN數(shù)據(jù)包將被發(fā)送到另一側(cè)以通知他們我們沒有更多數(shù)據(jù)要發(fā)送。

TA貢獻1995條經(jīng)驗 獲得超2個贊
close()
如果使用shutdown()
相反的話,可以避免一些限制。
close()
將終止TCP連接上的兩個方向。有時您想告訴另一個端點您已完成發(fā)送數(shù)據(jù),但仍希望接收數(shù)據(jù)。
close()
遞減描述符引用計數(shù)(在文件表條目中維護并計算當前打開的引用文件/套接字的描述符的數(shù)量),如果描述符不為0,則不關(guān)閉套接字/文件。這意味著如果要分配,只有在引用計數(shù)降為0后才會進行清理。shutdown()
一個可以啟動正常的TCP關(guān)閉序列,忽略引用計數(shù)。
參數(shù)如下:
int shutdown(int s, int how); // s is socket descriptor
int how
可:
SHUT_RD
或0
進一步接收是不允許的
SHUT_WR
或者1
不允許進一步發(fā)送
SHUT_RDWR
或者2
不允許進一步發(fā)送和接收
- 3 回答
- 0 關(guān)注
- 725 瀏覽
添加回答
舉報