首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

muduo shutdown() 機制解析:為何不直接關閉 TCP 連接

     編輯:關於C++

讀者提問:Daytime 伺服器範例中,主動關閉呼叫 conn->shutdown(),這不只是關閉寫入方向嗎?為何整個連接就關閉了?

程式碼追蹤

void TcpConnection::shutdown() {
    if (state_ == kConnected) {
        setState(kDisconnecting);
        loop_->runInLoop(boost::bind(&TcpConnection::shutdownInLoop, this));
    }
}

void TcpConnection::shutdownInLoop() {
    loop_->assertInLoopThread();
    if (!channel_->isWriting()) {
        socket_->shutdownWrite();  // 呼叫 ::shutdown(sockfd, SHUT_WR)
    }
}

設計原則:資料完整性優先

Muduo 不提供 close(),只提供 shutdown(),為了收發資料的完整性。

  • TCP 為全雙工協議,同一檔案描述符可讀可寫
  • shutdownWrite() 關閉「寫」方向,保留「讀」方向 → TCP half-close
  • 直接 close(socket_fd) 則雙向皆關閉

Half-Close 解決的問題

「當你打算關閉連接時,如何知道對方還有沒有資料在路上?」

Muduo 分兩階段關閉:

  1. 主動方先關本地「寫」端,發送 FIN
  2. 對方讀到 0 位元組(EOF),通常會主動關閉連接
  3. 主動方讀到 0 位元組,再關本地「讀」端

此期間若對方仍有資料發送,muduo 仍能正常接收並透過 message callback 通知應用層。

被動關閉行為

當 read() 回傳 0 時,muduo 回呼 connection callback,應用層得知對方斷開。若應用層不持有 TcpConnection 智慧指標,物件析構時 Socket RAII 析構函數呼叫 close(sockfd_) 真正關閉檔案描述符。

潛在安全風險與練習題

  • 若對方故意不關閉,連接持續 half-open 狀態消耗資源
  • 練習: 閱讀程式碼回答「被動關閉時 muduo 行為如何?」
  • 思考: shutdown() 後回呼 connection callback 間隔約一個 RTT,為什麼?

完整流程總結

  1. 發送完資料 → shutdownWrite() → 發送 FIN
  2. 對方讀到 0 → 關閉連接 (shutdownWrite 或 close)
  3. 我方讀到 0 → 回呼 connection callback → 引用計數歸零 → TcpConnection 析構 → Socket 析構 → close(sockfd_)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved