Getting the destination address of UDP packet

坚强是说给别人听的谎言 提交于 2019-12-25 06:12:09

问题


I have been using the following example posted in this same site. This is my version of it. (Please excuse my lack of experience with C socket programming:)

In constructor:

    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));
    }

Where "udpsocket_" is actually a boost asio udp socket. This is very convenient since on one hand I can have a function which gets the destination IP from the incoming UDP message without the need for using a raw socket:

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);
    }
}

Now here come the problems:

  • Could I call this "get_destination_IP" asynchronously, in a non-blocking way in the same way as I call "async_receive_from"?

As in:

  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
        )
  );
  • Function "recvmsg" stores the right destination IP info, but returns 0. In theory according to the man page, the "size_t numbytes" is returned there. Can I still read the datagram with "recvmsg"?

  • Is FD_ZERO necessary in the constructor?

  • Is FD_ZERO necessary at every call of "get_destination_IP"?

Thank you beforehand for your help


回答1:


See boost:asio::null_buffers() feature. If you pass boost::asio::null_buffers() to boost::asio async_*() functions then the handler is invoked when data is just available and you can (need to) receive it by yourself (eg, by recvmsg() in your case).

fdset is unused and useless there. Socket pooling is done by boost::asio for you.



来源:https://stackoverflow.com/questions/31101047/getting-the-destination-address-of-udp-packet

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!