I'm trying to set up a little test application on Linux (Ubuntu) based on some code I wrote (and that worked) for Winsock. As it stands now, it's just a little test that creates a socket (and seemingly successfully connects) only to hang eternally on recv() instead of receiving datagrams. It's a plain blocking socket.
Here's how I create it:
// Winsock commodities :)
typedef unsigned int SOCKET;
const unsigned int INVALID_SOCKET = -1;
static SOCKET Connect(const std::string &interfaceIP, const std::string &bindIP, unsigned int port)
{
// Create UDP socket.
SOCKET sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (INVALID_SOCKET != sock_fd)
{
// "Share" socket address.
int sockOpt = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&sockOpt), sizeof(int));
// Enlarge (or embiggen, if you will) recv. buffer.
sockOpt = 1024*512; // 0x80000;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char *>(&sockOpt), sizeof(int));
// Bind to interface(s).
sockaddr_in address;
memset(&address, 0, sizeof(sockaddr_in));
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = inet_addr(interfaceIP.c_str()); /* INADDR_ANY */
int addrLen = sizeof(sockaddr_in);
if (0 == bind(sock_fd, reinterpret_cast<sockaddr *>(&address), addrLen))
{
// Join multicast.
ip_mreq multicast;
multicast.imr_multiaddr.s_addr = inet_addr(bindIP.c_str());
multicast.imr_interface = address.sin_addr;
if (0 == setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<char *>(&multicast), sizeof(ip_mreq)))
{
// Non-blocking socket, please.
// fcntl(sock_fd, F_SETFL, O_NONBLOCK);
std::cout << "Socket joined multicast: " << bindIP.c_str() << ":" << port << std::endl;
return sock_fd;
}
}
close(sock_fd);
}
std::cout << "Failed to join multicast: " << bindIP.c_str() << ":" << port << std::endl;
return INVALID_SOCKET;
}
A few further things tested:
So clearly I'm overlooking something. Help greatly appreciated :-)
In Unix systems, when using a socket for multicast you should bind to INADDR_ANY, not to a interface.
Multicast filtering by interface (i.e. not receive mcast from other interfaces than the specified one) is already in place because you are correctly filling imr_interface.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With