在boost asio中是否有async_write_some供程式員以任何方式實作他們自己的類似于async_write的細粒度邏輯,等等:
class koebenhavn 。 public std::enable_shared_from_this< koebenhavn>
{
私有的。
boost::asio::ip::tcp::socket socket。
公共的。
...
void writing(std: :vector<const_buffer> & buffers, boost::asio::io_context::strand & strand){
/* io worker可以在傳輸的位元組數達到任意數量時回呼 */{
socket->async_write_some(buffers,
boost::asio::bind_executor(strand, [self=shared_from_this(), &buffers, &strand](boost::system::error_code error, size_t transferred){
/* lambda代替std::bind進行規范,如果有任何可能的多載*/。
self>writed(buffers, strand, error);
}));
}
void wrote(std::vector< const_buffer> & buffers。
boost::asio::io_context::strand & strand。
boost::system::error_code error, size_t transferred)/span>{
/* 我們需要推進緩沖區來發送其余位元組的參考 */{
if(! error){
/* 傳輸發生 */
if(transpired){
/* ----------------> 這里我們需要根據之前的緩沖區構建新的 "游標 "*/
std::vector<const_buffer> cursor = advance(buffers, transferred)。
/* <---------------- repeat! */
writing(cursor, strand);
}
}
}
...
};
我想要的是一個簡單的函式來推進緩沖區的序列,以便下一次呼叫重復。現在我懷疑在 asio 中沒有任何現成的輪子,是嗎?
在我的情況下,不使用async_write是有充分理由的。如果回答的話,請把它排除在外。
uj5u.com熱心網友回復:
你所期望的東西存在。它在DynamicBuffer概念中。
read|wrte_some成員函式是低級的,并且不接受動態緩沖區(它接受一個MutableBuffer的序列)。事實上,我堅持認為,使用這些函式在99%的情況下都不是你想要的。例如,請看這句話:
注釋
讀取操作可能無法讀取所有要求的位元組數。如果你需要確保在異步操作完成之前讀取所請求的資料量,請考慮使用async_read函式
。
人們經常對 IO 包的交付有錯誤的假設。只需使用async_read函式,而不是用你的動態緩沖器:
boost::asio::streambuf<
boost::asio::dynamic_buffer,用std::string變數等等。
自己動手吧
當然,你可以在任何低級介面(期望直接使用緩沖區)中使用動態緩沖區(即使用讀/寫 "游標")。但是然后你必須使用prepare()/consume()/commit()介面來管理游標(以及底層存盤中可能發生的分配)。
你可以將其與iostreams進行比較:代替int x; std::cin >> x;,你可以很好地使用底層的streambuf介面,但這只是更多的作業和錯誤。
當然,有時候我們可以使用底層的streambuf介面。
當然,有時你想要那個低級別的介面(例如,當你希望能夠更詳細地了解什么資料包在什么時間到達時),但我認為那是規則的例外。
獎勵:演示代碼
對你的問題代碼最簡單的修復方法是使用組成的寫操作:void writing(std: :vector<const_buffer> const& buffers, strand& strand)。
{
/* io作業者可以在傳輸的位元組數達到任意數量時回呼 */ 。
boost::asio::async_write(
socket, buffers,
bind_executor(strand, [self = shared_from_this(), strand])
(error_code ec, size_t transferred) {
std::cout << "transferred" << transferred << " bytes" "(" << ec.message() << ")" << std:: endl;
}));
這里的 "詛咒 "是由庫完成的。沒有任何問題。
注釋:
你可能更接受緩沖區型別,接受DynamicBuffer(v1/v2)和ConstBufferSequence的任何模型:
template <typeename Buffers> void writing(Buffers&& buffers, strand& strand) { /* io worker可以在傳輸的位元組數達到任意數量時回呼 */ boost::asio::async_write( socket, std::forward<Buffers>(buffers), bind_executor(strand, [self = shared_from_this(), strand]) (error_code ec, size_t transferred) { std::cout << "transferred" << transferred << " bytes" "(" << ec.message() << ")" << std:: endl; }));你可以將執行器與IO物件聯系起來,例如,像這樣:
koebenhavn(boost::asio::io_context& ctx) : socket_(make_strand(ctx)) { }現在你可以使用
(boost::aSilo::associated_executor(socket_)或者socket_.get_executor()或者當你在該套接字上發起任何異步操作時,讓庫默認做這個。template <typename Buffers> void writing(Buffers& & buffers) { /* io worker可在傳輸的位元組數達到任意數量時回呼 */ 寫入( socket, std::forward<Buffers> (buffers), [self = shared_from_this()](error_code ec, size_t transferred) { std::cout << "已傳輸" << transferred << " bytes""(" << ec.message() << ")" << std:: endl; }); }注意到事情變得簡單了嗎?是時候讓它重新變得復雜起來了。你的代碼有一個默認的假設:
writing(...)將被安全地呼叫,即從strand呼叫。既然我們不能確定這一點,那就考慮發布或派發到鏈上吧:dispatch( //) socket_.get_executor()。 [this, self, b = std::forward_as_tuple(buffers)] () mutable { async_write( //) socket_, std::get<0>(b)。 [self](error_code ec, size_t transferred) { std::cout << "transferred" << transferred << " bytes" "(" << ec.message() << ")" << std:: endl; }); });使用
dispatch的好處是,如果庫檢測到你已經在strand上,它可能會立即運行任務。
實時演示
Live On Coliru#include <boost/asio.hpp>
#include <iostream>
class koebenhavn : public std::enable_shared_from_this< koebenhavn> {
私有的。
boost::asio::ip::tcp::socket socket_;
using const_buffer = boost::asio::const_buffer;
using error_code = boost::system::error_code;
using strand = boost::asio::io_context::strand;
public:
koebenhavn(boost::assio::io_context& ctx)
: socket_(make_strand(ctx))
{ }
// io worker可以在傳輸的位元組數上任意回呼。
模板 <型別 Buffers> void writing(Buffers&& buffers)
{
auto self = shared_from_this();
dispatch( //)
socket_.get_executor()。
[this, self, b = std::forward_as_tuple(buffers)] () mutable {
async_write( //)
socket_, std::get<0>(b)。
[self](error_code ec, size_t transferred) {
std::cout << "transferred" << transferred << " bytes" "(" << ec.message() << ")" << std:: endl;
});
});
}
};
int main() {
boost::asio::io_context io。
auto k = std::make_shared<koebenhavn>(io)。
boost::asio::streambuf sb;
k->寫(sb)。
std::string s = "hello world
"。
k->寫(boost::ASIO::buffer(s))。
std::array<float, 7> ff{};
std:: vector<unsigned char> bb{{0, 1, 2, 3, 4}}。
k->寫(std::vector{
boost::ASIO::buffer(ff)。
boost::asio::buffer(bb)。
});
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/318021.html
標籤:
