Understanding Multicast Addresses and Implementation
Multicast Addressing Explained
For multicasting, a specific multicast address (Class D addresses, ranging from 224.0.0.0 to 239.255.255.255) is used to target a specific group of receivers.
Key Multicast Address Ranges
- 224.0.0.0 – 224.0.0.255: Local network control block.
- 224.0.1.0 – 238.255.255.255: Globally scoped multicast.
- 239.0.0.0 – 239.255.255.255: Administratively scoped, used for local/private multicast within organizations.
Multicast Sender Implementation
#define MULTICAST_GROUP "239.0.0.1" // Multicast group address (Class D)
#define MULTICAST_PORT 12345 // Port to send the message
#define MESSAGE "Hello, Multicast!"
int main() {
int sockfd;
struct sockaddr_in multicast_addr;
char *multicast_message = MESSAGE;
int loopback = 1; // Enable loopback for local system to receive the datagrams
// 1. Create a UDP socket (AF_INET, SOCK_DGRAM)
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
return 1;
}
// 2. Set the multicast address
memset(&multicast_addr, 0, sizeof(multicast_addr));
multicast_addr.sin_family = AF_INET;
multicast_addr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP);
multicast_addr.sin_port = htons(MULTICAST_PORT);
// 3. Enable loopback (optional, for local testing)
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loopback, sizeof(loopback)) < 0) {
perror("setsockopt");
close(sockfd);
return 1;
}
// 4. Send the multicast message
if (sendto(sockfd, multicast_message, strlen(multicast_message), 0, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr)) < 0) {
perror("sendto");
close(sockfd);
return 1;
}
printf("Message sent: %s\n", multicast_message);
close(sockfd);
return 0;
}
Multicast Receiver Implementation
#define MULTICAST_GROUP "239.0.0.1" // Multicast group address (Class D)
#define MULTICAST_PORT 12345 // Port to listen on
#define BUFFER_SIZE 1024
int main() {
int sockfd;
struct sockaddr_in local_addr;
struct ip_mreq multicast_request;
char buffer[BUFFER_SIZE];
int reuse = 1;
// 1. Create a UDP socket (AF_INET, SOCK_DGRAM)
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
return 1;
}
// 2. Allow multiple sockets to bind to the same address
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
perror("setsockopt");
close(sockfd);
return 1;
}
// 3. Bind to the multicast port
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = INADDR_ANY; // Listen on all interfaces
local_addr.sin_port = htons(MULTICAST_PORT);
if (bind(sockfd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
perror("bind");
close(sockfd);
return 1;
}
// 4. Join the multicast group
multicast_request.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP);
multicast_request.imr_interface.s_addr = INADDR_ANY; // Use default interface
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_request, sizeof(multicast_request)) < 0) {
perror("setsockopt");
close(sockfd);
return 1;
}
printf("Listening for multicast messages on %s:%d\n", MULTICAST_GROUP, MULTICAST_PORT);
// 5. Receive and print messages
while (1) {
socklen_t addr_len = sizeof(local_addr);
int bytes_received = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr *)&local_addr, &addr_len);
if (bytes_received < 0) {
perror("recvfrom");
close(sockfd);
return 1;
}
buffer[bytes_received] = '\0';
printf("Received: %s\n", buffer);
}
close(sockfd);
return 0;
}