在循环内使用 UDP 套接字时连接被拒绝

Connection refused when using a UDP socket inside a loop

考虑以下 MWE class foo,它有一个 send 成员函数,允许通过 UDP 将字符串发送到端口 1337 上的环回地址:

头文件:foo.h

#include <boost/asio.hpp>

class foo
{
public:

  foo(); // Constructor.
  void send(std::string const& message);

private:

  boost::asio::io_service ios;
  boost::asio::ip::udp::socket sock;
  boost::asio::ip::udp::endpoint endp;
};

执行文件:foo.cc

#include "foo.h"

foo::foo() : sock{ios}, endp{boost::asio::ip::address::from_string("127.0.0.1"), 1337}
{
    sock.connect(endp);
}

void foo::send(std::string const& message)
{
    sock.send(boost::asio::buffer(message));
}

现在我想使用 foo class 将字符串 Hello, World!\n 发送给自己。因此,在主函数中,我实例化了一个 foo 对象,然后我使用 for 循环调用了 foo.send() 5 次(两次爆发之间等待 1 秒)。

主要功能:

#include "foo.h"
#include <iostream>
#include <chrono>
#include <thread>

int main(int argc, char* argv[])
{
    foo foo;
    for(int i = 0; i<5; i++)
    {
        foo.send("Hello, World!\n");
        std::cout << i << std::endl;

        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }

    std::cout << "Done" << std::endl;

    return 0;
}

代码编译成功。但是,在运行时程序崩溃并抛出以下错误:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
  what():  send: Connection refused
Aborted (`core' dumped)

Connection refused 错误消息非常混乱,因为 UDP 在设计上是无连接的。所以无论收件人是否正在收听,程序都应该发送 5 条 UDP 消息。

我做错了什么?

UDP is connectionless by design. So the program should send 5 UDP messages whether the recipient is listening or not.

第一个不代表第二个。使用 UDP,不能保证错误报告,这与保证不报告错误有很大不同。通常,到达没有侦听器的端口的数据包将触发 ICMP 端口不可达消息返回给发送方,并且套接字 API 的大多数实现将在下一次尝试传输到同一个目的地。使用环回,检测错误对于网络堆栈来说更加容易。