要關閉一個Tcp客戶端,應該使用哪一個,io_context.stop()還是socket.close()?在做出這樣的選擇時,應該考慮哪些方面呢?
據我所知,io_context是執行緒安全的,而socket則不是。
因此,我可以在任何執行緒中呼叫io_context.stop(),該執行緒可能與呼叫io_context.run()的執行緒不同。
但是對于socket.close(),我需要呼叫io_context.post([=](){socket.stop()}),如果socket物件在不同的執行緒中被呼叫(例如,上述執行緒呼叫aiso::async_read(socket,...))。
uj5u.com熱心網友回復:
要關閉一個Tcp客戶端,應該使用哪一個,io_context.stop()還是socket.close()?
顯然是socket.cancel()和或socket.shutdown() :)
在只有一個IO物件(你的套接字)的情況下,停止整個iexecution背景關系似乎是等同的。但是一旦你打開了多個套接字,或者使用了定時器和信號集,這就很明顯了,為什么這是用大炮打蒼蠅。
還要注意的是,io_context::stop的副作用是清除任何未完成的作業(至少,在沒有reset()的情況下無法恢復),這使得它更像是一種鈍器。
相反,使用socket::cancel()來取消任何IO操作對它。它們將以error::operation_aborted完成,這樣你就可以檢測到這種情況。如果你控制物件上的所有異步啟動,這就足夠了。如果你想阻止 "其他 "方成功地啟動新的IO操作,你可以shutdown套接字。你可以關閉一個套接字的寫入端、讀取端或兩者都關閉。
關機通常優于close()的原因可能是相當微妙的。一方面,關閉一側使得你仍然可以處理/通知另一側以實作優雅的關閉。另一方面,當本機套接字句柄(也)被存盤在某個地方時,可以防止一個相當常見的競賽條件。關閉套接字使本機句柄有資格被重新使用,一個不知道這一變化的客戶端可以在以后繼續使用該句柄,而不知道它現在屬于其他人。我曾在生產代碼中看到過這樣的錯誤:在高負載下,RPC 呼叫會由于這種情況而突然被寫入資料庫服務器。
簡而言之,最好將套接字句柄與套接字實體的生命周期聯系起來,并且最好使用cancel()或shutdown()。
如果socket物件在不同的執行緒中被呼叫,我需要呼叫io_context.post(={socket.stop()})(例如,上述執行緒呼叫aiso::async_read(socket, ...) )。
是的,執行緒安全是你的責任。不,post(io_context, ...)甚至在多個執行緒運行執行背景關系時也是不夠的。在這種情況下,你需要更多的同步,比如post(strand_, ...)。參見為什么在使用boost::asio時我需要每個連接的strand?
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/325314.html
標籤:
