[英]boost::asio UDP server, how to send without having to do a receive_from first?
[英]Why doesn't boost::asio::ip::udp::socket::receive_from throw interruption exception in Windows?
volatile std::sig_atomic_t running = true;
int main()
{
boost::asio::thread_pool tpool;
boost::asio::signal_set signals(tpool, SIGINT, SIGTERM);
signals.async_wait([](auto && err, int) { if (!err) running = false; });
while(running)
{
std::array<std::uint8_t, 1024> data;
socket.recieve_from(boost::asio::buffer(data), ....); // (1)
// calc(data);
}
return 0;
}
如果我的代碼在 Linux 的 (1) 行中被阻止,並且我嘗試使用htop
提高信號,那么 (1) 行會引發有關中斷的異常,但在 Windows 中不會。 我不知道如何退出應用程序的問題。
我的程序需要做什么才能在兩個操作系統中同樣工作? 謝謝。
使用 Windows 10 (msvc 17)、Debian 11 (gcc-9)、Boost 1.78。
無論您如何在 Windows 上“發出信號”,基本問題是您依賴操作系統細節來取消同步操作。
取消是一項 ASIO 功能,但僅適用於異步操作。 所以,考慮:
signals.async_wait([&socket](auto&& err, int) {
if (!err) {
socket.cancel();
}
});
沒有 thread_pool 的簡化給出了例如:
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING 1
#include <boost/asio.hpp>
namespace asio = boost::asio;
using asio::ip::udp;
using boost::system::error_code;
struct Program {
Program(asio::any_io_executor executor)
: signals_{executor, SIGINT, SIGTERM}
, socket_{executor} //
{
signals_.async_wait([this](error_code ec, int) {
if (!ec) {
socket_.cancel();
}
});
socket_.open(udp::v4());
socket_.bind({{}, 4444});
receive_loop();
}
private:
asio::signal_set signals_;
udp::socket socket_;
std::array<std::uint8_t, 1024> data_;
udp::endpoint ep_;
void receive_loop() {
socket_.async_receive_from( //
asio::buffer(data_), ep_, [this](error_code ec, size_t) {
if (!ec)
receive_loop();
});
}
};
int main() {
asio::io_context ioc;
Program app(ioc.get_executor());
using namespace std::chrono_literals;
ioc.run_for(10s); // for COLIRU
}
打印(在大腸桿菌上):
@asio|1663593973.457548|0*1|signal_set@0x7ffe0b639998.async_wait
@asio|1663593973.457687|0*2|socket@0x7ffe0b6399f0.async_receive_from
@asio|1663593973.457700|.2|non_blocking_recvfrom,ec=system:11,bytes_transferred=0
@asio|1663593974.467205|.2|non_blocking_recvfrom,ec=system:0,bytes_transferred=13
@asio|1663593974.467252|>2|ec=system:0,bytes_transferred=13
@asio|1663593974.467265|2*3|socket@0x7ffe0b6399f0.async_receive_from
@asio|1663593974.467279|.3|non_blocking_recvfrom,ec=system:11,bytes_transferred=0
@asio|1663593974.467291|<2|
@asio|1663593975.481800|.3|non_blocking_recvfrom,ec=system:0,bytes_transferred=13
@asio|1663593975.481842|>3|ec=system:0,bytes_transferred=13
@asio|1663593975.481854|3*4|socket@0x7ffe0b6399f0.async_receive_from
@asio|1663593975.481868|.4|non_blocking_recvfrom,ec=system:11,bytes_transferred=0
@asio|1663593975.481878|<3|
@asio|1663593976.494097|.4|non_blocking_recvfrom,ec=system:0,bytes_transferred=13
@asio|1663593976.494138|>4|ec=system:0,bytes_transferred=13
@asio|1663593976.494150|4*5|socket@0x7ffe0b6399f0.async_receive_from
@asio|1663593976.494164|.5|non_blocking_recvfrom,ec=system:11,bytes_transferred=0
@asio|1663593976.494176|<4|
@asio|1663593976.495085|>1|ec=system:0,signal_number=2
@asio|1663593976.495119|1|socket@0x7ffe0b6399f0.cancel
@asio|1663593976.495129|<1|
@asio|1663593976.495151|>5|ec=system:125,bytes_transferred=0
@asio|1663593976.495162|<5|
@asio|1663593976.495184|0|socket@0x7ffe0b6399f0.close
@asio|1663593976.495244|0|signal_set@0x7ffe0b639998.cancel
所以這是 3 次成功接收,然后是信號 2 (INT) 和取消,導致 ec=125 ( asio::error:operation_aborted
) 並關閉。
使用多線程可能沒有任何好處,但如果這樣做,請使用鏈來同步對 IO 對象的訪問:
asio::thread_pool ioc;
Program app(make_strand(ioc));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.