[英]Force asynchronous socket read to finish early using Boost.Asio
我有一個tcp::socket
用於讀取和寫入數據。 通過鏈接async_read_some()
和處理程序on_data_read()
組成一個讀取循環,該處理程序在處理讀取的數據后再次調用async_read_some()
。 相關的shared_ptr<tcp::socket>
沿着循環傳遞。 當循環結束on_data_read()
是帶一個非成功error_code
如asio::error::eof
,在這種情況下async_read_some()
不被調用。
套接字上可能還會有異步寫入,這是通過重復調用async_write_some()
直到寫入所有數據來完成的。 也就是說,處理程序on_data_written()
為async_write_some()
調用async_write_some()
如果再次將數據僅部分寫入。 相關的shared_ptr<tcp::socket>
也沿調用鏈傳遞。
現在,我想以安全的方式關閉插座。 具體來說,我想用一個不成功的錯誤代碼來強制異步讀取盡早結束讀取循環。 如果沒有掛起的寫調用鏈,則唯一的shared_ptr<tcp::socket>
(沿着讀取循環傳遞的那個)將被關閉,並且其托管的tcp::socket
被銷毀。 如果有一個掛起的寫調用鏈,它會一直持續到所有數據都寫完為止。 在寫調用鏈結束時,最后一個shared_ptr<tcp::socket>
(沿着寫調用鏈傳遞的那個)被破壞了。 從某種意義上說,此過程是安全的,因為套接字在掛起的寫入(如果有)之后被關閉。
問題是
我已經檢查了纏綿選項。 但這不起作用,因為我使用的是鏈式async_write_some()
而不是單個async_write()
。 因此,可以在on_data_written()
關閉套接字。 cancel()
和close()
也不起作用,因為它們不僅中斷讀取循環,而且中斷寫入調用鏈。 而且,盡管shutdown()
可應用於讀取循環,但它僅阻止將來的async_read_some()
調用,並且對已完成的操作沒有影響。 我已經制定了一種解決方法。 也就是說,調用cancel()
,但是讓on_data_written()
忽略由cancel()
引起的錯誤代碼,並繼續執行寫調用鏈。 我對這種解決方案不滿意(請參閱此處的備注部分)。 我想知道是否有更直接,更優雅的方式來實現我想要的功能,或者整個設計存在缺陷?
我認為您已經很好地總結了這一點。
你真的不能做得比完全取消更好。 實際上,您可以恢復所有取消的寫入。
我認為沒有什么比這更優雅的了。 我不會說設計有缺陷,但是您可能要考慮不實際取消掛起的操作,而只是保留一個標志以指示“邏輯讀取取消”是否掛起並在這種情況下防止鏈接更多讀取
當您使用shutdown ..... socket.shutdown時,您是否使用了shutdown_both?
(boost :: asio :: ip :: tcp :: socket :: shutdown_both,ec)
shutdown_both選項。 那應該處理讀寫閉包。
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorcode);
if (errorcode)
{
cerr << "socket.shutdown error: " << errorcode.message() << endl;
}
另外,如果您具有io_service句柄。 您可以最后調用io_service.stop(),這將關閉所有操作。
關閉插座進行輸入。 這將導致所有掛起的讀取遇到流的末尾並相應地返回。
而且,盡管shutdown()僅可應用於讀取循環,但它僅阻止將來的async_read_some()調用,並且對已完成的操作沒有影響。
我不知道你從哪里得到這個錯誤信息。 我什至不知道這意味着什么。 關機適用於套接字,而不適用於讀取循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.