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
- One-to-many communication mode between hosts.
- All hosts in the same LAN can receive broadcast information.
- 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.
- Only UDP can broadcast.
- Broadcast address: valid network number + host number all 1.
- 192.168.114.83 —-》Class C IP address-》The first 24 bits of the network number -》192.168.114.255
- 192.168.125.229 —-》Class C IP address-》The first 24 bits of the network number -》192.168.125.255
- 144.1.2.3 —-》Class B IP address-》The first 16 bits of the network number-》144.1.255.255
- 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
- socket creates a report socket
- setsockopt sets allow broadcast level: SOL_SOCKET optname: SO_BROADCAST
- bind is not required to bind
- Fill in the address information of the recipient for use by the sendto function
- 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) - .PORT: needs to be consistent with the receiver binding.
- 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)
- sendto send data
- close closes the socket
66.2.2.3 Broadcast receiver process —-》Similar to UDP server
- socket creates a report socket
- Fill in the recipient’s own address information and use it for the bind function.
- IP: Broadcast IP: Valid network number + host number all 1 or 255.255.255.255 or 0.0.0.0 (any IP address)
- 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.
- All available IPs: local IP (192.168.125.5), 127.0.0.1 local loopback IP, broadcast IP, multicast IP
- PORT: 1024~49151 range;
- IP: Broadcast IP: Valid network number + host number all 1 or 255.255.255.255 or 0.0.0.0 (any IP address)
- bind must be bound
- recvfrom receives data
- 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
- 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.
- A one-to-one group communication method between hosts. Only hosts that have joined the same group can receive all data in this group.
- 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
- socket creates a report socket
- bind is not required to bind
- Fill in the address information of the recipient for use by the sendto function
- 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) - PORT: needs to be consistent with the receiver binding.
- IP: Multicast IP: 224.0.0.0~239.255.255.255
- sendto send data
- close closes the socket
66.2.3.3 Multicast receiver process -》Similar to UDP server
- socket creates a report socket
- 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 - Fill in the recipient’s own address information and use it for the bind function.
- .IP: Multicast IP: 224.0.0.0-239.255.255.255 or 0.0.0.0 (any IP address)
- 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.
- All available IPs: local IP (192.168.125.5), 127.0.0.1 local loopback IP, broadcast IP, multicast IP
- .PORT: 1024~49151 range;
- .IP: Multicast IP: 224.0.0.0-239.255.255.255 or 0.0.0.0 (any IP address)
- bind must be bound
- recvfrom receives data
- 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; }