增加 boost::beast unix 域套接字包装器的消息缓冲区大小
Increase message buffer size for boost::beast wrapper of unix domain socket
我正在使用 unix 域套接字的 boost::beast
包装器。我的平台是 macOS。
首先,我定义套接字:
boost::asio::local::stream_protocol::socket socket;
我想用它来阅读大小不超过 2k 的邮件。
boost::asio::streambuf input_streambuf;
...
boost::asio::async_read(socket, input_streambuf,
boost::asio::transfer_at_least(1), yield);
然而,input_streambuf只有512字节。
知道我是否可以从 Boost::beast 提高此限制吗?或者它可能是系统级别的一些定义?
谢谢
我在这里没有看到任何野兽类型。完全是 Asio。
此外,streambuf
模仿了 DynamicBuffer
概念。它没有固定尺寸,因此您的说法不准确。
最后,无论streambuf
的初始容量有多大,对你都没有多大好处,因为你将async_read
指示为transfer_at_least(1)
,这意味着底层实现中的任何 platform-dependent 缓冲区可能会导致第一个 read_some
到 return 数量小得多。例如。使用这个简单的服务器:
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <iostream>
namespace net = boost::asio;
using U = net::local::stream_protocol;
int main() {
net::thread_pool io;
using net::yield_context;
U::acceptor acc(io, "./test.sock");
acc.listen();
U::socket s = acc.accept();
spawn(io, [&](yield_context yield) { //
net::streambuf buf;
while (auto n = async_read(s, buf, net::transfer_at_least(1), yield))
std::cout << "Read: " << n << " (cumulative: " << buf.size() << ")"
<< std::endl;
});
io.join();
}
使用客户端时,例如:
netcat -U ./test.sock <<RESP
Hello world
This is Brussels calling
From pool to pool
RESP
将打印例如:
Read: 55 (cumulative: 55)
但是当运行宁netcat -U ./test.sock
交互时:
Read: 12 (cumulative: 12)
Read: 30 (cumulative: 42)
Read: 17 (cumulative: 59)
事实上,我们可以毫不夸张地向它扔上千本词典:
for a in {1..1000}; do cat /etc/dictionaries-common/words; done | netcat -U ./test.sock
输出为:
Read: 512 (cumulative: 512)
Read: 512 (cumulative: 1024)
Read: 512 (cumulative: 1536)
Read: 512 (cumulative: 2048)
Read: 512 (cumulative: 2560)
Read: 1536 (cumulative: 4096)
Read: 512 (cumulative: 4608)
Read: 3584 (cumulative: 8192)
Read: 512 (cumulative: 8704)
Read: 7680 (cumulative: 16384)
Read: 512 (cumulative: 16896)
Read: 15872 (cumulative: 32768)
Read: 512 (cumulative: 33280)
Read: 32256 (cumulative: 65536)
Read: 512 (cumulative: 66048)
Read: 65024 (cumulative: 131072)
Read: 512 (cumulative: 131584)
Read: 65536 (cumulative: 197120)
...
Read: 49152 (cumulative: 971409238)
Read: 49152 (cumulative: 971458390)
Read: 49152 (cumulative: 971507542)
Read: 49152 (cumulative: 971556694)
Read: 21306 (cumulative: 971578000)
terminate called after throwing an instance of 'boost::wrapexcept<boost::exception_detail::current_exception_std_exception_wrapper<std::runtime_error> >'
what(): End of file [asio.misc:2]
如您所见,缓冲区的大小取决于 OS,这实际上可以很好地按要求扩展它。
改进说明
因此,不要使用 transfer_at_least
,而是使用您认为合理的任何最小值:
while (auto n = async_read(s, buf, net::transfer_at_least(1024*1024), yield))
std::cout << "Read: " << n << " (cumulative: " << buf.size() << ")"
<< std::endl;
改为打印:
Read: 1048576 (cumulative: 1048576)
Read: 1048576 (cumulative: 2097152)
Read: 1063342 (cumulative: 3160494)
Read: 1086266 (cumulative: 4246760)
...
Read: 1086266 (cumulative: 969962524)
Read: 1102650 (cumulative: 971065174)
或者如果您愿意阅读到 EOF:
while (auto n = async_read(s, buf, yield[ec])) {
std::cout << ec.message() << ": " << n
<< " (cumulative: " << buf.size() << ")" << std::endl;
if (ec.failed())
break;
}
请注意,我们巧妙地添加了 error_code 检查,这样我们就不会因为 EOF 而错过整个传输。现在打印:
End of file: 971578000 (cumulative: 971578000)
最后,您可能想要限制最大容量,比如 50 Mib:
constexpr size_t _50MiB = 50<<20;
net::streambuf buf(_50MiB);
boost::system::error_code ec;
while (auto n = async_read(s, buf, yield[ec])) {
std::cout << ec.message() << ": " << n
<< " (cumulative: " << buf.size() << ")" << std::endl;
if (ec.failed())
break;
}
if (ec != net::error::eof && buf.size() == _50MiB) {
std::cout << "Warning: message truncated" << std::endl;
}
现在我们不能强制将字典提供给 运行 我们内存不足:
Success: 52428800 (cumulative: 52428800)
Warning: message truncated
我正在使用 unix 域套接字的 boost::beast
包装器。我的平台是 macOS。
首先,我定义套接字:
boost::asio::local::stream_protocol::socket socket;
我想用它来阅读大小不超过 2k 的邮件。
boost::asio::streambuf input_streambuf;
...
boost::asio::async_read(socket, input_streambuf,
boost::asio::transfer_at_least(1), yield);
然而,input_streambuf只有512字节。
知道我是否可以从 Boost::beast 提高此限制吗?或者它可能是系统级别的一些定义?
谢谢
我在这里没有看到任何野兽类型。完全是 Asio。
此外,streambuf
模仿了 DynamicBuffer
概念。它没有固定尺寸,因此您的说法不准确。
最后,无论streambuf
的初始容量有多大,对你都没有多大好处,因为你将async_read
指示为transfer_at_least(1)
,这意味着底层实现中的任何 platform-dependent 缓冲区可能会导致第一个 read_some
到 return 数量小得多。例如。使用这个简单的服务器:
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <iostream>
namespace net = boost::asio;
using U = net::local::stream_protocol;
int main() {
net::thread_pool io;
using net::yield_context;
U::acceptor acc(io, "./test.sock");
acc.listen();
U::socket s = acc.accept();
spawn(io, [&](yield_context yield) { //
net::streambuf buf;
while (auto n = async_read(s, buf, net::transfer_at_least(1), yield))
std::cout << "Read: " << n << " (cumulative: " << buf.size() << ")"
<< std::endl;
});
io.join();
}
使用客户端时,例如:
netcat -U ./test.sock <<RESP
Hello world
This is Brussels calling
From pool to pool
RESP
将打印例如:
Read: 55 (cumulative: 55)
但是当运行宁netcat -U ./test.sock
交互时:
Read: 12 (cumulative: 12)
Read: 30 (cumulative: 42)
Read: 17 (cumulative: 59)
事实上,我们可以毫不夸张地向它扔上千本词典:
for a in {1..1000}; do cat /etc/dictionaries-common/words; done | netcat -U ./test.sock
输出为:
Read: 512 (cumulative: 512)
Read: 512 (cumulative: 1024)
Read: 512 (cumulative: 1536)
Read: 512 (cumulative: 2048)
Read: 512 (cumulative: 2560)
Read: 1536 (cumulative: 4096)
Read: 512 (cumulative: 4608)
Read: 3584 (cumulative: 8192)
Read: 512 (cumulative: 8704)
Read: 7680 (cumulative: 16384)
Read: 512 (cumulative: 16896)
Read: 15872 (cumulative: 32768)
Read: 512 (cumulative: 33280)
Read: 32256 (cumulative: 65536)
Read: 512 (cumulative: 66048)
Read: 65024 (cumulative: 131072)
Read: 512 (cumulative: 131584)
Read: 65536 (cumulative: 197120)
...
Read: 49152 (cumulative: 971409238)
Read: 49152 (cumulative: 971458390)
Read: 49152 (cumulative: 971507542)
Read: 49152 (cumulative: 971556694)
Read: 21306 (cumulative: 971578000)
terminate called after throwing an instance of 'boost::wrapexcept<boost::exception_detail::current_exception_std_exception_wrapper<std::runtime_error> >'
what(): End of file [asio.misc:2]
如您所见,缓冲区的大小取决于 OS,这实际上可以很好地按要求扩展它。
改进说明
因此,不要使用 transfer_at_least
,而是使用您认为合理的任何最小值:
while (auto n = async_read(s, buf, net::transfer_at_least(1024*1024), yield))
std::cout << "Read: " << n << " (cumulative: " << buf.size() << ")"
<< std::endl;
改为打印:
Read: 1048576 (cumulative: 1048576)
Read: 1048576 (cumulative: 2097152)
Read: 1063342 (cumulative: 3160494)
Read: 1086266 (cumulative: 4246760)
...
Read: 1086266 (cumulative: 969962524)
Read: 1102650 (cumulative: 971065174)
或者如果您愿意阅读到 EOF:
while (auto n = async_read(s, buf, yield[ec])) {
std::cout << ec.message() << ": " << n
<< " (cumulative: " << buf.size() << ")" << std::endl;
if (ec.failed())
break;
}
请注意,我们巧妙地添加了 error_code 检查,这样我们就不会因为 EOF 而错过整个传输。现在打印:
End of file: 971578000 (cumulative: 971578000)
最后,您可能想要限制最大容量,比如 50 Mib:
constexpr size_t _50MiB = 50<<20;
net::streambuf buf(_50MiB);
boost::system::error_code ec;
while (auto n = async_read(s, buf, yield[ec])) {
std::cout << ec.message() << ": " << n
<< " (cumulative: " << buf.size() << ")" << std::endl;
if (ec.failed())
break;
}
if (ec != net::error::eof && buf.size() == _50MiB) {
std::cout << "Warning: message truncated" << std::endl;
}
现在我们不能强制将字典提供给 运行 我们内存不足:
Success: 52428800 (cumulative: 52428800)
Warning: message truncated