TCP/IP Network Programming Chapter Fourteen: Multicast and Broadcast

multicast

Multicast data transmission is based on UDP. So very close to UDP server/client implementation. The difference is that UDP data transfer is done with a single destination, while multicast data is delivered simultaneously to a large number of hosts joining a particular group. In other words, when multicast is used, data can be transmitted to multiple hosts at the same time.


Advantages of multicast data transmission method and flow

The characteristics of multicast data transmission can be organized as follows.
□The multicast server only sends data once for a specific multicast group.
□Even if the data is sent only once, all clients in the group will receive the data.
□The number of multicast groups can be increased arbitrarily within the IP address range.
□Join a specific group to receive the data sent to the multicast group.
The multicast group is a class D IP address (224.0.0.0~239.255.255.255). "Joining a multicast group" can be understood as completing the program through the
following statement: "In a class D IP address, I want to receive multicast data sent to the target 239.234.218.234." Multicast
is based on UDP, that is, the format of the multicast packet is the same as that of the UDP packet. It's just different from general UDP data packets. When delivering a multicast data packet to the network, the router will copy the data packet and deliver it to multiple hosts.

If a file is sent to 1000 hosts via TCP or UDP, a total of 1000 transfers are required. This is the case even if 10 hosts are combined into one network and 99% of the transmission paths are the same. But at this time, if you use the multicast method to transfer the file, you only need to send it once. At this time, the routers in the network composed of 1000 hosts are responsible for copying the files and passing them to the hosts. Because of this characteristic, multigrip is mainly used for "real-time transmission of multimedia data".

In addition, although multicast communication can be completed in theory, many routers do not support multicast, or even if they support multicast, they deliberately block multicast due to network congestion. Therefore, in order to complete multicast communication in routers that do not support multicast, tunneling (Tunneling) technology will also be used (this is not a problem that multicast program developers need to consider). We only discuss programming methods in environments that support multicast services.

Routing (Routing) and TTL (Time to Live, time to live), and the method of joining the group

Next, discuss multicast-related programming methods. In order to deliver multicast packets, TTL must be set. TTL is the abbreviation of Time to Live, and it is the main factor that determines the "packet transmission distance". TTL is represented by an integer, and it is decremented by 1 every time it passes through a router. When the TTL becomes 0, the data packet can no longer be delivered and can only be destroyed. Therefore, the value setting of TTL will affect the network traffic.

Next, the TTL setting method is given. The TTL setting in the program is done through the socket option in Chapter 9. The protocol layer related to setting
TTL is IPPROTO_IP, and the option name is IP_MULTICAST_TTL. Therefore, the TTL can
be set to 64 with the following code.

int send_sock;
int time_live=64;
.....
send_sock=socket(PF_INET,SOCK_DREAM,0);
setsockopt(send_sock,IPPROTO_IP,IP_MULTICAST_TTL,(void*)&time_live,sizeof(time_live));
...

In addition, adding people to the multicast group is also done by setting socket options. The protocol layer related to joining a multicast group is IPPROTO_IP, and
the option name is IP_ADD_MEMBERSHIP. You can join a multicast group through the following code.

int recv_sock;
struct ip_mreq join_addr;
....
recv_sock=socket(PF_INET,SOCK_DREAM,0);
....
join_addr.imr_mutiadr.s_addr="多播组地址信息";
join_addr.imr_interface.s_addr="加入多播组的主机地址信息";
setsockopt(recv_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(void*)&join_addr,sizeof(join_addr));
....

Here is another explanation of the ip_mreq structure, which is defined as follows.

struct ip_mreq{
     struct in_addr imr_multiaddr;
     struct in_addr imr_interface;
}

The third chapter talked about the in_addr structure, so only the structure members are introduced. First, the group IP address of the joining group is written in the first member imr_multiaddr. The second member imr_interface is the IP address of the host whose socket joins the group, and INADDR_ANY can also be used.

Implement multicast Sender and Receiver

In multicast, "sender" (hereinafter referred to as Sender) and "receiver" (hereinafter referred to as Receiver) are used to replace the server and client. As the name implies, the Sender here is the sending subject of multicast data, and the Receiver is the data receiving subject that needs to join the multicast group. The forthcoming example, discussed below, runs in the following scenario.

□Sender: Broadcasting (Broadcasting) the news information saved in the file to the AAA group.
□Receiver: Receive the news information delivered to the AAA group.

Next give the Sender code. Sender is simpler than Receiver, because Receiver needs to go through the process of joining the group, while
Sender only needs to create a UDP socket and send data to the multicast address.

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

#define TTL 64
#define BUF_SIZE 30
void error_hangling(char *message);

int main(int argc,char *argv[]){
    int send_sock;
    struct sockaddr_in mul_addr;
    int time_live=TTL;
    FILE *fp;
    char buf[BUF_SIZE];
    if(argc!=3){
         printf("Usage : %s <GroupIP><PORT>\n",argv[0]);
         exit(1);
    }

    send_sock=socket(PF_INET,SOCK_DREAM,0);
    memset(&mul_addr,0,sizeof(mul_addr));
    mul_addr.sin_family=AF_INET;
    mul_addr.sin_addr_s.addr=inet_addr(argv[1]);//多播组IP
    mul_addr.sin_port=htons(atoi(argv[2]));//多播组端口

    setsockopt(send_sock,IPPROTO_IP,IP_MULTICAST_TTL,(void*)&time_live,sizeof(time_live));
    if((fp=fopen("news.txt","r"))==NULL)error_handling("fopen() error");

    while(!feof(fp)){//广播内容
        fgets(buf,BUF_SIZE,fp);
        sendto(send_sock,buf,strlen(buf),0,(struct sockaddr*)&mul_addr,sizeof(mul_addr));
        //上面也可以优化为持久连接
        sleep(2);
    }
    fclose(fp);
    close(send_sock);
    return 0;
}

void error_handling(char *message){
    fputs(message,stderr);
    fputc('\n',stderr);
    exit(1);
}

Next, the Receiver program used in conjunction with the above example is given.

#include<"与发送端的头文件声明相同,故省略">
#define BUF_SIZE 30
void error_handling(char *message);

int main(int argc,char *argv[]){
    int recv_sock;
    int str_len;
    char buf[BUF_SIZE];
    struct sockaddr_in addr;
    struct ip_mreq join_addr;
    if(argc!=3){
        printf("Usage : %s <GroupIP> <PORT>\n",argv[0]);
        exit(1);
    }

    recv_sock=socket(PF_INET,SOCK_DREAM,0);
    memset(&addr,0,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=htonl(INADDR_ANY);
    addr.sin_port=htons(atoi(argv[2]));

    if(bind(recv_sock,(struct sockaddr*)&addr,sizeof(addr))==-1)
         error_handling("bind() error");

    join_addr.imr_multiaddr.s_addr=inet_addr(argv[1]);
    join_addr.imr_interface.s_addr=htonl(INADDR_ANY);
 
    setsockopt(recv_sock,IPPROTO_IP,IP_ADDR_MEMBERSHIP, 
    (void*)&join_addr,sizeof(join_addr));

    while(1){
        str_len=recvfrom(recv_sock,buf,BUF_SIZE-1,0,NULL,0);
        if(str_len<0)break;
        buf[str_len]=0;
        fputs(buf,stdout);
    }
    close(recv_sock);
    return 0;
}

void error_handling(char *message){
    //和发送端的内容相同,故省略
}

broadcast

The broadcast (Broadcast) introduced in this section is similar to multicast in terms of "sending data to multiple hosts at one time", but the range of data output is different. Multicast can receive data by joining a multicast group even if it spans different networks. In contrast, broadcasts can only transmit data to hosts on the same network.

Understanding and Implementation of Broadcasting

Broadcasting is a method of transmitting data to all hosts on the same network . Like multicast, broadcast is also done based on UDP.
According to the format of the IP address used when transmitting data, broadcasting is divided into the following two types.
□Direct Broadcast (Directed Broadcast)
□Local Broadcast (Local Broadcast)
The difference in code implementation between the two mainly lies in the IP address.

In the direct broadcast IP address, except the network address, all other host addresses are set to 1 . For example, if you want to transmit data to all hosts in the network address 192.12.34, you can transmit to 192.12.34.255. In other words, you can use direct broadcast to transmit data to all hosts in a specific area.
Conversely, the IP address used in local broadcasts is limited to 255.255.255.255 . For example, when a host in the 192.32.24 network
transmits data to 255.255.255.255, the data will be delivered to all hosts in the 192.32.24 network.
So, how should Sender and Receiver be implemented? In fact, it is difficult to distinguish from the UDP example without carefully observing the IP addresses used for communication in the broadcast example. That said, the IP address used in the data communication is the only difference from the UDP example. Sockets generated by default block broadcasts, therefore. Just change the default settings by code like below.

int send_sock;
int bcast = 1;//对变量进行初始化以将SO_BROADCAST选项信息改为1。
....
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
....
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST,(void*)&bcast, sizeof(bcast));
....


Call the setsockopt function with the SO_BROADCAST option set to the value 1 in the bcast variable.
This means data broadcasting is possible . Of course, the above socket options only need to be changed in Sender, the implementation of Receiver does not need this process.

Realize the Sender and Receiver of broadcast data

The following implements broadcast-based Sender and Receiver.

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

#define BUF_SIZE 30
void error_handling(char *message);

int main(int argc, char *argv[]){
    int send_sock;
    struct sockaddr_in broad_adr;
    FILE *fp;
    char buf[BUF_SIZE];
    int so_brd=1;
    if(argc!=3){
         printf("Usage : %s <Boradcast IP><PORT>\n",argv[e]);
         exit(1);
    }

    send_sock=socket(PF_INET,SOCK_DGRAM,0);
    memset(&broad_adr, 0, sizeof(broad_adr));
    broad_adr.sin_family=AF_INET;
    broad_adr.sin_addr.s_addr=inet_addr(argv[1]);
    broad_adr.sin_port=htons(atoi(argv[2]));

    setsockopt(send sock, SOL_SOCKET,SO_BROADCAST,(void*)&so_brd, sizeof(so_brd));
    if((fp=fopen("news.txt","r"))==NULL)error_handling("fopen() error");

    while(!feof(fp)){
       fgets(buf,BUF_SIZE,fp);
       sendto(send_sock,buf,strlen(buf),0,(struct sockaddr*)&broad_adr, sizeof(broad_adr));
       sleep(2);
    }
    close(send_sock);
    return 0;
}

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

Line 29 changes the options of the UDP socket created in line 23 so that it can send broadcast data, and the rest is consistent with UDPsender. Next, broadcast Receiver is given.

#include<"与上一篇示例头文件声明相同,故省略">
#define BUF_SIZE 30
void error_handling(char *message);

int main(int argc, char *argv[]){
    int recv_sock;
    struct sockaddr_in adr;
    int str_len;
    char buf[BUF_SIZE];
    if(argc!=2){
       printf("Usage : %s <PORT>\n", argv[0]);
       exit(1);
    }

    recv_sock=socket(PF_INET,SOCK_DGRAM,0);
    memset(&adr,0, sizeof(adr));
    adr.sin_family=AF_INET;
    adr.sin_addr.s_addr=htonl(INADDR_ANY);
    adr.sin_port=htons(atoi(argv[1]));

    if(bind(recv_sock,(struct sockaddr*)&adr, sizeof(adr))==-1)
           error_handling("bind() error");
    while(1){
    str_len=recvfrom(recv_sock, buf, BUF_SIZE-1, 0, NULL, 0);
    if(str_len<0)
        break;
    buf[str_len]=0;
    fputs(buf,stdout);
    }
    close(recv_sock);
    return 0;
}

void error_handling(char *message)
   //与上一个函教一致,故省略
}

Windows-based implementation

Implementing the above example on the Windows platform requires no changes, as the previous content applies here as well. Just in multicast, the header file example is slightly different. The declaration of ws2tcpip.h needs to be added, which defines the IP_MULTICAST_TTL option and the ip_mreq structure.

Guess you like

Origin blog.csdn.net/Reol99999/article/details/131804005