【问题标题】:Getting the destination address of UDP packet获取UDP数据包的目的地址
【发布时间】:2015-06-28 14:42:07
【问题描述】:

我一直在使用在同一站点上发布的以下example。这是我的版本。 (请原谅我缺乏 C 套接字编程经验:)

在构造函数中:

    server::server(io_service& io_service, const int port) : 
       udpsocket_(io_service, udp::endpoint(udp::v4(), port))) {

       int sock = udpsocket_.native();
       fd_set fdset;
       FD_ZERO(&fdset);
       FD_SET(sock, &fdset);
       int opt = 1;
       setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
    }

其中“udpsocket_”实际上是一个boost asio udp 套接字。这非常方便,因为一方面我可以有一个函数从传入的 UDP 消息中获取目标 IP,而无需使用原始套接字:

void get_destination_IP() {

    int sock = udpsocket_.native();
    char cmbuf[0x100];
    struct sockaddr_in peeraddr;
    struct msghdr mh;
    mh.msg_name = &peeraddr;
    mh.msg_namelen = sizeof(peeraddr);
    mh.msg_control = cmbuf;
    mh.msg_controllen = sizeof(cmbuf);
    int received = recvmsg(sock, &mh, 0);
    for ( // iterate through all the control headers
            struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
            cmsg != NULL;
            cmsg = CMSG_NXTHDR(&mh, cmsg))
    {
        if (cmsg->cmsg_level != IPPROTO_IP ||
                cmsg->cmsg_type != IP_PKTINFO)
        {
            continue;
        }
        struct in_pktinfo *pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
        char* destAddr = (char*) calloc(4, sizeof(char));
        destAddr = inet_ntoa(pi->ipi_spec_dst);

        stored_UDP_dest_ip_ = ip::address::from_string(destAddr);
    }
}

现在问题来了:

  • 我能否像调用“async_receive_from”一样以非阻塞方式异步调用此“get_destination_IP”?

如:

  udpsocket_.async_receive_from(
        boost::asio::buffer(msg_),
        udp_endpoint_,
        boost::bind(&server::UDP_recv_handler,
                this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred,
                handler
        )
  );
  • 函数“recvmsg”存储正确的目标 IP 信息,但返回 0。理论上根据手册页,“size_t numbytes”在那里返回。我还能用“recvmsg”读取数据报吗?

  • FD_ZERO 必须在构造函数中使用吗?

  • 每次调用“get_destination_IP”时都需要 FD_ZERO 吗?

提前感谢您的帮助

【问题讨论】:

  • Could I call this "get_destination_IP" 在您显示的代码中没有名为 get_destination_IP 的函数。 in the same way as I call "async_receive_from"? 在您显示的代码中,您不会以任何方式调用 async_receive_fromIs FD_ZERO necessary here? FD_ZERO 在哪里需要? Is FD_ZERO necessary at every call of the function? 每次调用哪个函数?
  • 我不知道 boost API,但通常 - 任何可能阻塞 I/O 的东西都可以异步方式调用。 select 是一种机制,或者您可以拥有更新的基于 epoll 的 API。很难说出为什么recvmsg 返回零,而不查看其他代码,因为手册页说这意味着另一端关闭连接。 FD_ZERO 在构造函数中是必需的,因为您想要关闭对所有描述符的兴趣,但您创建的套接字除外。在 get_destination_IP 中 - 我认为不需要 - 事实上 FD_ZEROFD_SET 会使其变得不必要的麻烦。

标签: c++ linux sockets udp boost-asio


【解决方案1】:

参见 boost:asio::null_buffers() 功能。如果您将 boost::asio::null_buffers() 传递给 boost::asio async_*() 函数,则当数据可用时调用处理程序并且您可以(需要)自己接收它(例如,通过 recvmsg()在你的情况下)。

fdset 在那里没有使用和无用。套接字池由 boost::asio 为您完成。

【讨论】:

    猜你喜欢
    • 2011-07-13
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    • 1970-01-01
    • 2020-05-03
    • 1970-01-01
    • 2017-09-26
    相关资源
    最近更新 更多