[英]May boost::asio::ip::udp::socket::send_to even fail?
Please consider following code snippet.请考虑以下代码片段。
It first resolves address of remote host, then opens socket and sends some data to it.它首先解析远程主机的地址,然后打开套接字并向其发送一些数据。 Note, it throws immediately when error occurs.
请注意,发生错误时它会立即抛出。
No concurrency involved.不涉及并发。 Message fits to 1K.
消息适合 1K。 Basically the only difference between this code snippet and "real" code is following: message may be sent in several seconds after endpoint was resolved and socket is opened.
基本上,此代码段和“真实”代码之间的唯一区别如下:在解决端点并打开套接字后几秒钟内可能会发送消息。
using namespace boost::asio;
io_context io_context;
ip::udp::resolver resolver{io_context};
const auto endpoints = resolver.resolve(ip::udp::v4(), "host", "port");
if (endpoints.empty())
throw std::runtime_error("No endpoints found");
const auto endpoint = endpoints->endpoint();
ip::udp::socket socket{io_context};
socket.open(ip::udp::v4());
const auto message = buffer("asdf"); // fits to 1K
// may the line below fail provided the code above is executed successfully?
socket.send_to(message, endpoint);
For me, provided the endpoint is valid and socket is opened successfully, it seems that call to socket.send_to
should be always successful, even if remote host becomes unavailable (since UDP is used).对我来说,只要端点有效并且套接字已成功打开,似乎对
socket.send_to
的调用应该总是成功的,即使远程主机不可用(因为使用了 UDP)。
ASIO implements this in terms of underlying operating system calls. ASIO 在底层操作系统调用方面实现了这一点。 On POSIX, that would be
sendto
.在 POSIX 上,这将是
sendto
。 The possible error conditions are documented (see below).记录了可能的错误情况(见下文)。
However, first things first:但是,首先要做的是:
You could receive a segfault for addressing out of bounds into unknown address space.您可能会收到一个段错误,用于越界寻址到未知地址空间。 Depending on your platform it might manifest as
EFAULT
( boost::asio::error::fault
).根据您的平台,它可能表现为
EFAULT
( boost::asio::error::fault
)。
const_buffer buffer{"asdf", 10};
The preferred spelling here is:这里的首选拼写是:
auto buffer = boost::asio::buffer("asdf"); // char[5] includes NUL
Which will send the char[]
(including terminating NUL character) (see overload ).它将发送
char[]
(包括终止 NUL 字符)(请参阅重载)。 If you don't want that, consider eg boost::asio::buffer("asdf"sv)
, which uses a string view, without you having to call strlen
.如果您不希望这样,请考虑使用字符串视图的
boost::asio::buffer("asdf"sv)
,而无需调用strlen
。
Note how you create naming conflicts where
buffer
hidesboost::asio::buffer
because ofusing namespace
.请注意,由于
using namespace
,buffer
隐藏boost::asio::buffer
时如何创建命名冲突。 You did the same withio_context
.你对
io_context
做了同样的事情。 I'd advise against this level of flirting with danger in C++我建议不要在 C++ 中进行这种程度的危险调情
if (ec)
throw std::system_error(ec);
Is not needed.不需要。 If you don't supply
ec
, the exception boost::system::system_error
(but from boost) will already be raised in the same fashion.如果您不提供
ec
,异常boost::system::system_error
(但来自 boost)将以相同的方式引发。
size_t sent = socket.send_to(
ba::buffer("asdf"),
endpoints->endpoint());
You use endpoints->endpoint()
without validating the resolver results.您使用
endpoints->endpoint()
而不验证解析器结果。 Depending on situation zero or more resolutions might exist.根据情况,可能存在零个或多个分辨率。 You might be dereferencing an invalid iterator.
您可能正在取消引用无效的迭代器。 This, again, can cause error conditions.
这同样会导致错误情况。
You can get inspiration from the POSIX documentation: https://pubs.opengroup.org/onlinepubs/009695399/functions/sendto.html您可以从 POSIX 文档中获得灵感: https://pubs.opengroup.org/onlinepubs/009695399/functions/sendto.html
The vast majority of the conditions are not applicable, partly due to it绝大多数条件不适用,部分原因是它
However a few remain:但是仍然有一些:
EACCESS
can occur if you use a regular endpoint as if it were multicastEACCESS
EDESTADDRREQ
if you pass an invalid endpoint (eg default constructed) EDESTADDRREQ
如果你传递了一个无效的端点(例如默认构造)EINTR
unless you have signals ignored EINTR
除非您忽略了信号ENOBUFS
(when the adapter is jammed - doesn't happen on linux where packets are just dropped) ENOBUFS
(当适配器卡住时 - 不会发生在刚刚丢弃数据包的 linux 上) Depending on the actual arguments in your real code:根据实际代码中的实际 arguments :
EMSGSIZE
if your buffer exceeds the limit that can be sent atomically EMSGSIZE
如果您的缓冲区超过了可以自动发送的限制EOPNOTSUPP
if you pass invalid flags EOPNOTSUPP
如果您传递无效标志The real question is: do you anticipate any errors that you should deal with?真正的问题是:您是否预计应该处理任何错误? If not simply accept the exceptions (I suggest not passing
error_code
parameters).如果不是简单地接受异常(我建议不要传递
error_code
参数)。
The only such condition I can think of is a failure to resolve the hostname.我能想到的唯一这样的情况是无法解析主机名。 However, a quick test tells me the resultset will not be empty, but instead
resolve
throws Host not found (authoritative)
.但是,快速测试告诉我结果集不会为空,而是
resolve
抛出Host not found (authoritative)
。
So, just simplify:因此,只需简化:
#include <boost/asio.hpp>
using namespace std::literals;
namespace ba = boost::asio;
using ba::ip::udp;
int main() {
ba::io_context io;
udp::resolver resolver{io};
auto endpoints = resolver.resolve(udp::v4(), "127.0.0.1", "6767");
udp::socket socket{io};
socket.open(udp::v4());
return socket.send_to(ba::buffer("asdf"sv), endpoints->endpoint());
}
With和
nc -u -l -p 6767 & sleep 1; ./a.out
Prints印刷
asdf
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.