【问题标题】:How to do disconnect on UDP socket using boost::asio如何使用 boost::asio 断开 UDP 套接字
【发布时间】:2012-12-19 04:16:59
【问题描述】:

结合来自boost docsmanual for connect function 的信息,我认为asio::udp::socket::connect 函数用于设置默认发送数据报的地址,以及接收数据报的唯一地址。

这很好用,但手册还指出我应该能够解除关联(断开连接),这就是我遇到的问题。 IE。我希望套接字再次开始接收来自任何地址的数据包。

手册中进一步写到:

Connectionless sockets may dissolve the association by connecting to an
address with the sa_family member of sockaddr set to AF_UNSPEC.

我试过这段代码:

asio::udp::endpoint unspecified_endpoint;
assert(unspecified_endpoint.address().is_unspecified()); // OK
socket.connect(unspecified_endpoint);

但这并没有帮助。


编辑:通过从 boost::asio 页面获取 clientserver 示例创建了一个测试用例。在客户端代码中,我已将传出端口号从随机更改为 5192:

udp::socket s(io_service, udp::endpoint(udp::v4(), 5192));

并且我在服务器代码中更改了函数server

void server(boost::asio::io_service& io_service, short port)
{
  udp::socket sock(io_service, udp::endpoint(udp::v4(), port));

#define CASE 3

#if CASE == 1
  sock.connect(udp::endpoint());
#elif CASE == 2
  sock.connect(udp::endpoint(ip::address::from_string("127.0.0.1"), 5193));
  sock.connect(udp::endpoint());
#elif CASE == 3
  sock.connect(udp::endpoint(ip::address::from_string("192.168.1.3"), 5192));
  sock.connect(udp::endpoint());
#endif

  for (;;)
  {
    char data[max_length];
    udp::endpoint sender_endpoint;
    size_t length = sock.receive_from(
    boost::asio::buffer(data, max_length), sender_endpoint);
    sock.send_to(boost::asio::buffer(data, length), sender_endpoint);
  }
}

案例 1 和 2 似乎有效,但在案例 3 中,客户端不会收到回复。完整源码可以在here找到。

【问题讨论】:

  • UDP 不是面向连接的。
  • @bbg,确实,但连接不是我想要完成的。该函数被称为 connect 有点误导,但它所做的只是为传入和传出数据包的地址设置一个过滤器。我遇到的问题是删除此过滤器。
  • boost asio 代码实际上通过带有未指定 IP 地址的 AF_INET 进行连接(而不是 AF_UNSPEC),但这似乎仍然适用于我的 Linux 系统。您正在使用什么操作系统,您可以将代码发布到完整(最小)的示例中吗?
  • @cmeerw,我添加了一个测试代码示例。我在使用内核 3.2.0 的 linux 上。感谢收看。

标签: udp boost-asio


【解决方案1】:

如 cmets 中所述,对 sock.connect(udp::endpoint()); 的调用转换为 connect(6, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0,这与带有 AF_UNSPECconnect 不同,并且不会完全断开 UDP 套接字(它似乎只会重置对等端口号)。

我认为没有一种方法可以纯粹使用 boost asio 来实现您想要的,但您可以使用本机 POSIX 调用来断开套接字,例如

struct sockaddr unspec_addr = { AF_UNSPEC };
::connect(sock.native_handle(), &unspec_addr, sizeof(unspec_addr));

调试说明:使用strace 运行程序,然后使用netstat -nu 列出UDP 套接字。

【讨论】:

    【解决方案2】:

    要保持对库函数的访问,请使用 udp::endpoint 只是 sockaddr 的包装器这一事实。使用特定值构造 sockaddr 并将其转换为所需的类型。

    sock.connect(reinterpret_cast<const udp::endpoint &>(static_cast<const sockaddr &>(sockaddr{ AF_UNSPEC })));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      • 2010-12-31
      相关资源
      最近更新 更多