Embedded Development Plan-30-Network Programming—-Multipoint Communication–Unicast–Broadcast–Multicast

Sixty-six, multipoint communication

66.1 Network attribute related functions

  • getsockopt
  • setsockopt
Function:
Get/set network properties;
prototype:
       #include <sys/types.h> /* See NOTES */
       #include <sys/socket.h>

       int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
       int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
Parameters:
    int sockfd:
    Specifies which socket's network properties are to be set;
    int level:
    Specify the hierarchical level to be controlled;
SOL_SOCKET: specifies the application layer, general socket option;
IPPROTO_TCP: Specifies that TCP is to be controlled;
IPPROTO_UDP:UDP
IPPROTO_IP: IP
    int optname:
    Specify operation name, option name.
    After the second parameter specifies the level to be, this parameter is used to specify what controls the level;
    \t
       ---- SOL_SOCKET : man 7 socket ----
        1. Whether SO_BROADCAST allows broadcasting (only UDP allows broadcasting) ---》optval: int* type
        2. Whether SO_REUSEADDR allows quick port reuse ---》optval: int* type, and it is a bool type;
       ---- IPPROTO_TCP : man 7 TCP ----
       ---- IPPROTO_UDP : man 7 UDP ----
       ---- IPPROTO_IP : man 7 IP ----
        1. IP_ADD_MEMBERSHIP joins multicast (multicast group) ----》optval: struct ip_mreqn* type
           struct ip_mreqn {<!-- -->
               struct in_addr imr_multiaddr; /* IP multicast group address */
               struct in_addr imr_address; /* IP address of local interface */
               int imr_ifindex; /* interface index */
           };
        
    void *optval:
    Unless otherwise stated, optval is of type int*
    \t
    socklen_t *optlen/socklen_t optlen:
    The actual data type size pointed to by the optval pointer;
return value:
    Success, return 0;
    On failure, return -1 and update errno;

  • Example:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

int main(int argc, const char *argv[])
{<!-- -->
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sfd < 0)
    {<!-- -->
        perror("socket");
        return -1;
    }
    printf("socket create success \
");

    socklen_t len;
    int reuse = 100;

    //Set to allow quick port reuse
    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, & amp;reuse, sizeof(reuse)) < 0)
    {<!-- -->
        perror("setsockopt");
        return -1;
    }
    printf("Set to allow fast port reuse\
");

    //Determine whether fast port reuse is allowed by default
    len = sizeof(reuse);
    if(getsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, & amp;reuse, & amp;len) < 0)
    {<!-- -->
        perror("getsockopt");
        return -1;
    }
    printf("%d\
", reuse);


    //Set to allow broadcast
    int broad = 1;
    if(setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, & amp;reuse, sizeof(reuse)) < 0)
    {<!-- -->
        perror("setsockopt");
        return -1;
    }
    printf("Set to allow broadcast\
");

    //Determine whether broadcasting is allowed by default
    len = sizeof(broad);
    if(getsockopt(sfd, SOL_SOCKET, SO_BROADCAST, & amp;broad, & amp;len) < 0)
    {<!-- -->
        perror("getsockopt");
        return -1;
    }
    printf("broad = %d\
", broad);

    //Get the size of the receive buffer
    int rcvbuf;
    len = sizeof(rcvbuf);
    if(getsockopt(sfd, SOL_SOCKET, SO_RCVBUF, & amp;rcvbuf, & amp;len) < 0)
    {<!-- -->
        perror("getsockopt");
        return -1;
    }
    printf("rcvbuf = ?ytes %dkb\
", rcvbuf, rcvbuf/1024);

    struct timeval tm;
    len = sizeof(tm);
    if(getsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, & amp;tm, & amp;len) < 0)
    {<!-- -->
        perror("getsockopt");
        return -1;
    }
    printf("%lds %ldus\
", tm.tv_sec, tm.tv_usec);

    close(sfd);
    return 0;
}

66.2 Multipoint Communication

66.2.1 Unicast

  • One-to-one communication mode between hosts,
  • Only two entities communicate with each other at a time, and both the sender and the receiver are uniquely identified.

66.2.2 Broadcast

66.2.2.1 Concept

  1. One-to-many communication mode between hosts.
  2. All hosts in the same LAN can receive broadcast information.
  3. Broadcast data is prohibited from passing through the router, that is, it is limited to the current LAN. Prevent affecting a large area of hosts.
  4. Only UDP can broadcast.
  5. Broadcast address: valid network number + host number all 1.
    1. 192.168.114.83 —-》Class C IP address-》The first 24 bits of the network number -》192.168.114.255
    2. 192.168.125.229 —-》Class C IP address-》The first 24 bits of the network number -》192.168.125.255
    3. 144.1.2.3 —-》Class B IP address-》The first 16 bits of the network number-》144.1.255.255
    4. 255.255.255.255

255.255.255.255: Send broadcast data to all network segments in all networks, but since it cannot pass through the router, it can only be sent to the host in the current LAN.

66.2.2.2 Broadcast sender process —-》Similar to UDP client

  1. socket creates a report socket
  2. setsockopt sets allow broadcast level: SOL_SOCKET optname: SO_BROADCAST
  3. bind is not required to bind
  4. Fill in the address information of the recipient for use by the sendto function
    1. IP: Broadcast IP: Valid network number + host number all 1 or 255.255.255.255 (needs to be consistent with what is specified when binding the receiver)
      (PS: It is not allowed to fill in 0.0.0.0. If both the receiver and the sender fill in 0.0.0.0, 127.0.0.1 communication will be used by default)
    2. .PORT: needs to be consistent with the receiver binding.
  5. sendto send data
  6. close closes the socket

66.2.2.3 Broadcast receiver process —-》Similar to UDP server

  1. socket creates a report socket
  2. Fill in the recipient’s own address information and use it for the bind function.
    1. IP: Broadcast IP: Valid network number + host number all 1 or 255.255.255.255 or 0.0.0.0 (any IP address)
      1. 0.0.0.0: When the bind function is called to bind, all available IP addresses of the local machine will be bound to the socket.
      2. All available IPs: local IP (192.168.125.5), 127.0.0.1 local loopback IP, broadcast IP, multicast IP
    2. PORT: 1024~49151 range;
  3. bind must be bound
  4. recvfrom receives data
  5. close closes the socket

66.2.2.4 Broadcast sample code

  • Sender
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <string.h>
    
    #define ERR_MSG(msg) do{<!-- -->\
        fprintf(stderr, "__%d__ ", __LINE__);\
        perror(msg);\
    }while(0)
    
    #define SER_PORT 8888 //The port number bound by the receiver
    #define SER_IP "192.168.125.255" //Broadcast IP
    
    int main(int argc, const char *argv[])
    {<!-- -->
        //Create a report socket
        int cfd = socket(AF_INET, SOCK_DGRAM, 0);
        if(cfd < 0)
        {<!-- -->
            ERR_MSG("socket");
            return -1;
        }
        printf("socket create success cfd=%d\
    ", cfd);
    
        //Set to allow broadcast
        int broad = 1;
        if(setsockopt(cfd, SOL_SOCKET, SO_BROADCAST, & amp;broad, sizeof(broad)) < 0)
        {<!-- -->
            ERR_MSG("setsockopt");
            return -1;
        }
        printf("Set allowed broadcast successfully\
    ");
    
        //Bind the client's own address information ---> Binding is not required
        //If not bound, the operating system will bind the local IP and random port to the client.
    
        //Fill in the address information structure for use by the sendto function. Fill in the address information of whomever you want to send it to.
        //The real address information structure is specified according to the address family AF_INET: man 7 IP
        struct sockaddr_in sin;
        sin.sin_family = AF_INET; //AF_INET is required;
        sin.sin_port = htons(SER_PORT); //The port number bound by the receiver
        sin.sin_addr.s_addr = inet_addr(SER_IP); //The IP bound to the receiver
    
        char buf[128] = "";
        ssize_t res = 0;
        while(1)
        {<!-- -->
            bzero(buf, sizeof(buf));
            printf("Please enter >>> ");
            fgets(buf, sizeof(buf), stdin);
            buf[strlen(buf)-1] = 0;
    
            //Send data, proactively send it to the designated receiver. For example, you can proactively send it to the receiver here.
            if(sendto(cfd, buf, sizeof(buf), 0, (struct sockaddr*) & amp;sin, sizeof(sin)) < 0)
            {<!-- -->
                ERR_MSG("sendto");
                return -1;
            }
            printf("sendto success\
    ");
        }
        //Close the socket
        close(cfd);
    
        return 0;
    }
    
  • Receiver
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <string.h>
    
    #define ERR_MSG(msg) do{<!-- -->\
        fprintf(stderr, "__%d__ ", __LINE__);\
        perror(msg);\
    }while(0)
    
    #define PORT 8888 //Network byte order of port number, 1024~49151
    #define IP "192.168.125.255" //Broadcast
    
    int main(int argc, const char *argv[])
    {<!-- -->
        //Create a report socket
        int sfd = socket(AF_INET, SOCK_DGRAM, 0);
        if(sfd < 0)
        {<!-- -->
            ERR_MSG("socket");
            return -1;
        }
        printf("socket create success sfd=%d\
    ", sfd);
    
        //Fill the address information structure for use by the bind function
        //The real address information structure is specified according to the address family AF_INET: man 7 IP
        struct sockaddr_in sin;
        sin.sin_family = AF_INET; //AF_INET is required;
        sin.sin_port = htons(PORT); //Network byte order of port number, 1024~49151
        sin.sin_addr.s_addr = inet_addr(IP); //Broadcast IP
    
        //Bind the recipient's own address information
        if(bind(sfd, (struct sockaddr*) & amp;sin, sizeof(sin)) < 0)
        {<!-- -->
            ERR_MSG("bind");
            return -1;
        }
        printf("bind success\
    ");
    
        struct sockaddr_in cin; //Storage address information sent
        socklen_t addrlen =sizeof(cin);
    
        char buf[128] = "";
        ssize_t res = 0;
        while(1)
        {<!-- -->
            bzero(buf, sizeof(buf));
            //Receive data --->Also store where this data packet comes from, that is, the sending address
            res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*) & amp;cin, & amp;addrlen);
            if(res < 0)
            {<!-- -->
                ERR_MSG("recvfrom");
                return -1;
            }
            printf("[%s:%d] : %s\
    ", \
                    inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);
        }
        //Close the socket
        close(sfd);
        return 0;
    }
    

66.2.3 Multicast

66.2.3.1 Concept

  1. The broadcast method is to send data to all hosts in the same network segment. Excessive broadcasts will occupy a large amount of bandwidth and affect normal communication.
  2. A one-to-one group communication method between hosts. Only hosts that have joined the same group can receive all data in this group.
  3. Multicast IP: Class D IP address: 224.0.0.0~239.255.255.255

66.2.3.2 Multicast sender process -》Similar to UDP client

  1. socket creates a report socket
  2. bind is not required to bind
  3. Fill in the address information of the recipient for use by the sendto function
    1. IP: Multicast IP: 224.0.0.0~239.255.255.255
      PS: It is not allowed to fill in 0.0.0.0. If both the receiver and the sender fill in 0.0.0.0, 127.0.0.1 communication will be used by default)
    2. PORT: needs to be consistent with the receiver binding.
  4. sendto send data
  5. close closes the socket

66.2.3.3 Multicast receiver process -》Similar to UDP server

  1. socket creates a report socket
  2. setsockopt Join a group (join a multicast group) The group you join and the group you are bound to must be consistent
    level: IPPROTO_IP
    optname: IP_ADD_MEMBERSHIP
  3. Fill in the recipient’s own address information and use it for the bind function.
    1. .IP: Multicast IP: 224.0.0.0-239.255.255.255 or 0.0.0.0 (any IP address)
      1. 0.0.0.0: When the bind function is called to bind, all available IP addresses of the local machine will be bound to the socket.
      2. All available IPs: local IP (192.168.125.5), 127.0.0.1 local loopback IP, broadcast IP, multicast IP
    2. .PORT: 1024~49151 range;
  4. bind must be bound
  5. recvfrom receives data
  6. close closes the socket

66.2.3.4 Join multicast group

Function:
Set network properties;
prototype:
       #include <sys/types.h> /* See NOTES */
       #include <sys/socket.h>

       int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
Parameters:
    int sockfd:
    Specifies which socket's network properties are to be set;
    int level:
    Specify the hierarchical level to be controlled;
        IPPROTO_IP: IP
    int optname:
    Specify operation name, option name.
    After the second parameter specifies the level to be, this parameter is used to specify what controls the level;
    \t
       ---- IPPROTO_IP : man 7 IP ----
       
        1. IP_ADD_MEMBERSHIP joins multicast (multicast group) ----》optval: struct ip_mreqn* type
           struct ip_mreqn {<!-- -->
struct in_addr imr_multiaddr; /* IP multicast group address */ Specifies the network byte order of the multicast IP to be added
struct in_addr imr_address; /* IP address of local interface */ Network byte order of local IP
int imr_ifindex; /* interface index */ Network device index number (network card number)
1. Ifconfig checks the network card name of this machine: ens33. Enter ip ad in the terminal to find the number corresponding to ens33: 2
2. if_nametoindex("network card name"), the return value is the number. if_nametoindex("ens33")
3. Fill in 0, automatic (default network card)
           };

        
    void *optval: Unless otherwise stated, optval is of type int*
    socklen_t *optlen/socklen_t optlen: the real data type size pointed to by the optval pointer;
return value:
    Success, return 0;
    On failure, return -1 and update errno;

66.2.3.5 Multicast sample code

  • Sender
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <string.h>
    
    #define ERR_MSG(msg) do{<!-- -->\
        fprintf(stderr, "__%d__ ", __LINE__);\
        perror(msg);\
    }while(0)
    
    #define SER_PORT 8888 //The port number bound by the receiver
    #define SER_IP "224.1.2.3" //Multicast IP: 224.0.0.0-239.255.255.255
    
    int main(int argc, const char *argv[])
    {<!-- -->
        //Create a report socket
        int cfd = socket(AF_INET, SOCK_DGRAM, 0);
        if(cfd < 0)
        {<!-- -->
            ERR_MSG("socket");
            return -1;
        }
        printf("socket create success cfd=%d\
    ", cfd);
    
        //Bind the client's own address information ---> Binding is not required
        //If not bound, the operating system will bind the local IP and random port to the client.
    
        //Fill in the address information structure for use by the sendto function. Fill in the address information of whomever you want to send it to.
        //The real address information structure is specified according to the address family AF_INET: man 7 IP
        struct sockaddr_in sin;
        sin.sin_family = AF_INET; //AF_INET is required;
        sin.sin_port = htons(SER_PORT); //Multicast port
        sin.sin_addr.s_addr = inet_addr(SER_IP); //Multicast IP
    
        char buf[128] = "";
        ssize_t res = 0;
        while(1)
        {<!-- -->
            bzero(buf, sizeof(buf));
            printf("Please enter >>> ");
            fgets(buf, sizeof(buf), stdin);
            buf[strlen(buf)-1] = 0;
    
            //Send data, proactively send it to the designated receiver. For example, you can proactively send it to the receiver here.
            if(sendto(cfd, buf, sizeof(buf), 0, (struct sockaddr*) & amp;sin, sizeof(sin)) < 0)
            {<!-- -->
                ERR_MSG("sendto");
                return -1;
            }
            printf("sendto success\
    ");
        }
        //Close the socket
        close(cfd);
        return 0;
    }
    
  • Receiver
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <string.h>
    
    #define ERR_MSG(msg) do{<!-- -->\
        fprintf(stderr, "__%d__ ", __LINE__);\
        perror(msg);\
    }while(0)
    
    #define PORT 8888 //Network byte order of port number, 1024~49151
    #define GRP_IP "224.1.2.3" //Multicast IP 224.0.0.0-239.255.255.255
    #define LOL_IP "192.168.125.5" //Ifconfig's local IP
    
    int main(int argc, const char *argv[])
    {<!-- -->
        //Create a report socket
        int sfd = socket(AF_INET, SOCK_DGRAM, 0);
        if(sfd < 0)
        {<!-- -->
            ERR_MSG("socket");
            return -1;
        }
        printf("socket create success sfd=%d\
    ", sfd);
    
        //Join multicast group
        struct ip_mreqn mq;
    
        mq.imr_multiaddr.s_addr = inet_addr(GRP_IP); //Multicast IP
        mq.imr_address.s_addr = inet_addr(LOL_IP); //Local IP, ifconfig
        mq.imr_ifindex = 2; //Network device index number
    
        if(setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, & amp;mq, sizeof(mq)) < 0)
        {<!-- -->
            ERR_MSG("setsockopt");
            return -1;
        }
        printf("Joined multicast group [%s] successfully\
    ", GRP_IP);
    
        //Fill the address information structure for use by the bind function
        //The real address information structure is specified according to the address family AF_INET: man 7 IP
        struct sockaddr_in sin;
        sin.sin_family = AF_INET; //AF_INET is required;
        sin.sin_port = htons(PORT); //Network byte order of port number, 1024~49151
        sin.sin_addr.s_addr = inet_addr(GRP_IP); //Multicast IP
    
        //Bind the recipient's own address information
        if(bind(sfd, (struct sockaddr*) & amp;sin, sizeof(sin)) < 0)
        {<!-- -->
            ERR_MSG("bind");
            return -1;
        }
        printf("bind success\
    ");
    
        struct sockaddr_in cin; //Storage address information sent
        socklen_t addrlen =sizeof(cin);
    
        char buf[128] = "";
        ssize_t res = 0;
        while(1)
        {<!-- -->
            bzero(buf, sizeof(buf));
            //Receive data --->Also store where this data packet comes from, that is, the sending address
            res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*) & amp;cin, & amp;addrlen);
            if(res < 0)
            {<!-- -->
                ERR_MSG("recvfrom");
                return -1;
            }
            printf("[%s:%d] : %s\
    ", \
                    inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);
        }
        //Close the socket
        close(sfd);
        return 0;
    }