讀者提問: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(),為了收發資料的完整性。
shutdownWrite() 關閉「寫」方向,保留「讀」方向 → TCP half-closeclose(socket_fd) 則雙向皆關閉「當你打算關閉連接時,如何知道對方還有沒有資料在路上?」
Muduo 分兩階段關閉:
此期間若對方仍有資料發送,muduo 仍能正常接收並透過 message callback 通知應用層。
當 read() 回傳 0 時,muduo 回呼 connection callback,應用層得知對方斷開。若應用層不持有 TcpConnection 智慧指標,物件析構時 Socket RAII 析構函數呼叫 close(sockfd_) 真正關閉檔案描述符。
shutdown() 後回呼 connection callback 間隔約一個 RTT,為什麼?shutdownWrite() → 發送 FINclose(sockfd_)