How to do multicast (multicast) programming in Linux c/c++

Chapter 1: Preface

Multicasting, also known as "groupcasting", is a network communication mechanism that allows one node (sender) to send a message to a specific group of nodes (receivers). This approach is very useful in network programming as it can greatly improve efficiency and performance while reducing network bandwidth usage.

In unicast communication, information is sent from one node to another node, while in broadcast communication, information is sent from one node to all nodes in the network. Multicast is somewhere in between, where information is sent from one node to a specific set of nodes. This method is especially suitable for scenarios where information needs to be sent to a specific group of hosts, such as online video conferencing or real-time data sharing.

Multicast implementation relies on class D IP addresses, ranging from 224.0.0.0 to 239.255.255.255. These addresses are divided into link-local multicast addresses, reserved multicast addresses, and administrative rights multicast addresses. The host can request the router to join or exit a multicast group, and then the router and the switch will selectively copy and transmit the data, and only transmit the data to the hosts in the group.

Advantages of multicast technology include:

  1. Bandwidth Efficiency : Multicast allows data to be shared among hosts in the same group, saving network bandwidth.

  2. Server load : Since the multicast protocol determines whether to forward data streams based on the needs of the receivers, the bandwidth on the server side is constant and has nothing to do with the number of clients.

  3. WAN Support : Unlike broadcasting, multicasting can be performed over a wide area network such as the Internet.

However, multicast technology also has some disadvantages:

  1. No error correction mechanism : Compared with unicast, multicast has no error correction mechanism, and it is difficult to make up for errors, but this function can be realized at the application layer.

  2. Network support : The network support of multicast has flaws and requires the support of routers and network protocol stacks.

In general, multicast technology is a powerful network communication mechanism, which is very useful in many scenarios, such as online video, online conference, etc. However, to use multicast effectively, you need to understand how it works and ensure that network devices and protocol stacks support multicast correctly.

Chapter 2: Multicasting in Wide Area Networks

Multicast is a network communication mechanism that allows one node (sender) to send information to a group of nodes (receivers). This approach is very useful in network programming because it can greatly improve efficiency and performance.

In IP networking, multicast addresses are defined as Class D IP addresses ranging from 224.0.0.0 to 239.255.255.255. These addresses are divided into three categories:

  1. Link-local multicast addresses : This range is from 224.0.0.0 to 224.0.0.255. These addresses are mainly used for local communication between network devices, such as communication between routers. Packets for these addresses will not be forwarded by the router to other networks.

  2. Reserved multicast address : This range is from 224.0.1.0 to 238.255.255.255. These addresses can be used worldwide, for example on the Internet. This means that if your application needs to send information to multiple nodes around the world, you can use addresses in this range.

  3. Administrative rights multicast address : This range is from 239.0.0.0 to 239.255.255.255. These addresses are similar to private IP addresses and can only be used within a specific organization or enterprise. Packets for these addresses cannot be routed on the Internet, so they can be used to limit the reach of multicasts.

There are a few things you need to be aware of when using multicast addresses. First, you need to make sure that your network equipment (such as routers and switches) supports multicast and is properly configured. Second, you need to choose the correct multicast address to ensure that your message is correctly sent to the target node.

Hope this explanation helps you gain a deeper understanding of multicast and multicast addresses in WAN. If you have other questions, please feel free to ask me.

Chapter 3: Multicast Programming

Multicasting is a way of sending information in a network that allows a node to send information to a group of nodes rather than to each node individually. This approach is very useful in network programming because it can greatly improve efficiency and performance.

In multicast programming, we use some special socket options to control multicast behavior. These options are usually set at the IP layer, since multicast is implemented at the IP layer.

  1. IP_MULTICAST_TTL : This option is used to set the time-to-live (TTL) of multicast packets. TTL is a value between 0 and 255 that determines how many routers a packet can pass through. Every time a packet passes through a router, its TTL is decremented by 1, and when the TTL reaches 0, the packet is dropped. This option prevents multicast packets from spreading unrestrictedly across the network.

  2. IP_MULTICAST_IF : This option is used to set the default multicast interface. Multicast packets will be sent from this interface, other interfaces will ignore these packets.

  3. IP_MULTICAST_LOOP : This option is used to control whether multicast packets are allowed to loop back locally. If set to 1, packets will be looped back locally; if set to 0, packets will not be looped back locally.

  4. IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP : These two options are used to control whether a node joins or leaves a multicast group. When a node joins a multicast group, it can receive all packets sent to the group.

When writing a multicast program, we usually follow the following steps:

  1. Create a socket : We first need to create a socket to send and receive data.

  2. Set multicast parameters : Then, we need to set multicast parameters, such as TTL and local loopback.

  3. Joining a multicast group : Next, we need to join the node to a multicast group.

  4. Sending and receiving data : Once a node has joined a multicast group, it can start sending and receiving data.

  5. Leaving the multicast group : Finally, when a node no longer needs to receive multicast data, it can leave the multicast group.

The following is an example of multicast programming written in C++. In this example, we will create a sender and a receiver, the sender will send data to a multicast group, and the receiver will receive the data.

First, we create a sender:

#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() {
    
    
    // 创建套接字
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
    
    
        std::cerr << "Error creating socket" << std::endl;
        return -1;
    }

    // 设置多播TTL参数
    unsigned char ttl = 1;
    if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
    
    
        std::cerr << "Error setting multicast TTL" << std::endl;
        return -1;
    }

    // 设置目标地址
    sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("239.0.0.1"); // 多播地址
    addr.sin_port = htons(12345); // 目标端口

    // 发送数据
    std::string msg = "Hello, Multicast!";
    if (sendto(sock, msg.c_str(), msg.size(), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
    
    
        std::cerr << "Error sending data" << std::endl;
        return -1;
    }

    std::cout << "Data sent to multicast group" << std::endl;

    return 0;
}

Then, we create a receiver:

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() {
    
    
    // 创建套接字
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
    
    
        std::cerr << "Error creating socket" << std::endl;
        return -1;
    }

    // 绑定到本地地址和端口
    sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意本地地址
    addr.sin_port = htons(12345); // 目标端口

    if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
    
    
        std::cerr << "Error binding socket" << std::endl;
        return -1;
    }

    // 加入多播组
    ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr("239.0.0.1"); // 多播地址
    mreq.imr_interface.s_addr = htonl(INADDR_ANY); // 任意网络接口

    if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
    
    
        std::cerr << "Error joining multicast group" << std::endl;
        return -1;
    }

    // 接收数据
    char buf[1024];
    memset(buf, 0, sizeof(buf));
    if (recv(sock, buf, sizeof(buf), 0) < 0) {
    
    
        std::cerr << "Error receiving data" << std::endl;
        return -1;
    }

    std::cout << "Received data: " << buf << std::endl;

    // 离开多播组
    if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
    
    
        std::cerr << "Error leaving multicast group" << std::endl;
        return -1;
    }

    return 0;
}

Chapter 4: In-depth understanding of multicast in the Linux kernel

In the Linux kernel, the multicast function is realized through a series of well-designed data structures and corresponding operations. This chapter will explore these data structures in depth, including struct ip_mc_socklist, struct ip_mreqnand struct ip_sf_socklist, and how to manipulate these data structures through IP_ADD_MEMBERSHIPand IP_DROP_MEMBERSHIPoptions to achieve multicast functionality.

4.1 The core data structure of multicast: ip_mc_socklist

In the Linux kernel, multicasting is struct ip_mc_socklistimplemented through data structures. This data structure connects various aspects of multicast, including multicast TTL (Time To Live), whether to enable multicast loopback, multicast device serial number, multicast address, and multicast group.

4.2 Join and leave multicast group: IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP

In Linux, we can IP_ADD_MEMBERSHIPadd a local IP address to a multicast group through options. This process mainly includes copying user data to the kernel, checking the validity of the multicast IP address, finding the corresponding network interface, checking whether the multicast address already exists in the multicast list, and adding the multicast address to the list.

Instead, we can pass IP_DROP_MEMBERSHIPoptions to remove a local IP address from a multicast group. This process mainly includes copying user data to the kernel, finding the corresponding network interface, checking whether the multicast address already exists in the multicast list, and removing the multicast address from the source address and the multicast list.

4.3 Source filtering: ip_sf_socklist

In the Linux kernel, we can struct ip_sf_socklistimplement source filtering through data structures. This data structure contains a list of source addresses, the number of source addresses in the list and the maximum capacity of the list. We can use this data structure to control which sources of multicast datagrams are accepted and which sources of multicast datagrams are excluded.

By deeply understanding these data structures and operations, we can better understand the multicast functionality in the Linux kernel and how to use multicast in our applications. In the next chapter, we will discuss how to use the multicast function of Linux in practical applications.

A multicast server-side example

Below is an example of an improved multicast server side. This sample program will continue to send data "BROADCAST TEST DATA" to port 8888 of the multicast IP address "224.0.0.88", with an interval of 5s between each sending.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MCAST_PORT 8888
#define MCAST_ADDR "224.0.0.88"
#define MCAST_DATA "BROADCAST TEST DATA"
#define MCAST_INTERVAL 5

int main(void)
{
    
    
    int sockfd;
    struct sockaddr_in mcast_addr;

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
    
    
        perror("socket");
        exit(EXIT_FAILURE);
    }

    // 初始化多播地址
    memset(&mcast_addr, 0, sizeof(mcast_addr));
    mcast_addr.sin_family = AF_INET;
    mcast_addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);
    mcast_addr.sin_port = htons(MCAST_PORT);

    // 循环发送多播数据
    while (1)
    {
    
    
        int n = sendto(sockfd, MCAST_DATA, sizeof(MCAST_DATA), 0, (struct sockaddr*)&mcast_addr, sizeof(mcast_addr));
        if (n == -1)
        {
    
    
            perror("sendto");
            exit(EXIT_FAILURE);
        }

        // 等待一段时间
        sleep(MCAST_INTERVAL);
    }

    close(sockfd);

    return 0;
}

The flow of this procedure is as follows:

insert image description here

  1. Create a socket.
  2. Initialize the multicast address.
  3. Set the protocol family to AF.
  4. Set the multicast IP address.
  5. Set the multicast port.
  6. Start a loop, sending data to the multicast address.
  7. Wait for a while.
  8. Go back to step 6.

The improvement of this program is that it is more concise and pays more attention to error handling, ensuring that it can exit in time and give an error message when an error occurs. At the same time, it also pays more attention to resource management, ensuring that the socket is closed at the end of the program.

An example of a multicast client

Below is an example of an improved multicast client. This sample program will join the multicast group "224.0.0.88", listen on port 8888, receive and print out the data received from the multicast group.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MCAST_PORT 8888
#define MCAST_ADDR "224.0.0.88"
#define MCAST_INTERVAL 5
#define BUFF_SIZE 256

int main(void)
{
    
    
    int sockfd;
    struct sockaddr_in local_addr;
    struct ip_mreq mreq;
    char buff[BUFF_SIZE];
    int n;

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
    
    
        perror("socket");
        exit(EXIT_FAILURE);
    }

    // 初始化本地地址
    memset(&local_addr, 0, sizeof(local_addr));
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    local_addr.sin_port = htons(MCAST_PORT);

    // 绑定socket
    if (bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr)) == -1)
    {
    
    
        perror("bind");
        exit(EXIT_FAILURE);
    }

    // 设置回环许可
    int loop = 1;
    if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) == -1)
    {
    
    
        perror("setsockopt: IP_MULTICAST_LOOP");
        exit(EXIT_FAILURE);
    }

    // 加入多播组
    mreq.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
    {
    
    
        perror("setsockopt: IP_ADD_MEMBERSHIP");
        exit(EXIT_FAILURE);
    }

    // 循环接收多播组的消息
    for (int times = 0; times < 5; times++)
    {
    
    
        socklen_t addr_len = sizeof(local_addr);
        memset(buff, 0, BUFF_SIZE);

        n = recvfrom(sockfd, buff, BUFF_SIZE, 0, (struct sockaddr*)&local_addr, &addr_len);
        if (n == -1)
        {
    
    
            perror("recvfrom");
            exit(EXIT_FAILURE);
        }

        // 打印信息
        printf("Recv %dst message from server: %s\n", times, buff);

        // 等待一段时间
        sleep(MCAST_INTERVAL);
    }

    // 退出多播组
    if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
    {
    
    
        perror("setsockopt: IP_DROP_MEMBERSHIP");
        exit(EXIT_FAILURE);
    }

    close(sockfd);

    return 0;
}

The flow of this procedure is as follows:

insert image description here

  1. Create a socket.
  2. Initialize the local address.
  3. Bind the socket.
  4. Set loopback permission.
  5. Join a multicast group.
  6. Start the loop and receive data.
  7. Print information.
  8. Wait for a while.

Guess you like

Origin blog.csdn.net/qq_21438461/article/details/131021736