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
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.