sk2:multicast_example
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| sk2:multicast_example [2016/11/22 08:38] – jkonczak | sk2:multicast_example [2025/11/27 18:49] (current) – jkonczak | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ==== Przykład użycia UDP multicast ==== | ==== Przykład użycia UDP multicast ==== | ||
| - | <code cpp multicast_example> | + | <code cpp multicast_example.cpp> |
| + | #include <csignal> | ||
| #include < | #include < | ||
| - | #include <csignal> | + | #include <cstdlib> |
| - | #include < | ||
| #include < | #include < | ||
| + | #include < | ||
| - | #include < | ||
| #include < | #include < | ||
| #include < | #include < | ||
| + | #include < | ||
| - | #include < | ||
| - | #include < | ||
| #include < | #include < | ||
| + | #include < | ||
| + | #include < | ||
| /* UDP multicast example. Compile with threads and C++11 (g++ -pthread --std=c++11) | /* UDP multicast example. Compile with threads and C++11 (g++ -pthread --std=c++11) | ||
| - | | + | * |
| * Sending to multicast group MCASTIP: | * Sending to multicast group MCASTIP: | ||
| | | ||
| | | ||
| - | | + | * |
| * Receiving datagrams sent to a multicast group MCASTIP: | * Receiving datagrams sent to a multicast group MCASTIP: | ||
| | | ||
| Line 27: | Line 28: | ||
| | | ||
| | | ||
| - | | + | * |
| * setsockopt of IP_ADD_MEMBERSHIP sends an IGMP message "join group" and tells OS that the program waits for messages for the group. | * setsockopt of IP_ADD_MEMBERSHIP sends an IGMP message "join group" and tells OS that the program waits for messages for the group. | ||
| - | * | + | * |
| - | * More info at: http://www.tldp.org/ | + | * More info at: https:// |
| */ | */ | ||
| - | + | const sockaddr_in groupSockaddr{ | |
| - | const sockaddr_in groupSockaddr { | + | .sin_family = AF_INET, |
| - | .sin_family = AF_INET, | + | .sin_port = htons(6789), |
| - | .sin_port = htons(6789), | + | .sin_addr = {.s_addr = inet_addr(" |
| - | .sin_addr = {inet_addr(" | + | |
| }; | }; | ||
| - | std:: | + | std:: |
| - | void ctrl_c(int){ | + | void ctrl_c(int) { |
| - | if(quitting) | + | if (quitting) |
| - | exit(-1); | + | exit(-1); |
| - | quitting = true; | + | quitting = true; |
| } | } | ||
| void setupSignals(); | void setupSignals(); | ||
| - | int main(int argc, char **argv) { | + | int main() { |
| - | + | ||
| - | // create socket | + | // create socket |
| - | int sockfd = socket(PF_INET, | + | int sockfd = socket(PF_INET, |
| - | if(sockfd==-1) error(1, | + | if (sockfd == -1) |
| - | + | | |
| - | // set SO_REUSEADDR (or only one app will be allowed to receive multicast messages from the groupIP: | + | |
| - | // this is one of very few cases when SO_REUSEADDR on UDP has any use | + | // set SO_REUSEADDR (or only one app will be allowed to receive multicast messages from the groupIP: |
| - | const int one = 1; | + | const int one = 1; |
| - | int res = setsockopt(sockfd, | + | int res = setsockopt(sockfd, |
| - | if(res) error(1, | + | if (res) |
| - | + | | |
| - | // bind | + | |
| - | sockaddr_in myAddress { | + | // bind |
| - | .sin_family = AF_INET, | + | sockaddr_in myAddress{ |
| - | .sin_port = groupSockaddr.sin_port, | + | .sin_family = AF_INET, |
| - | .sin_addr = {INADDR_ANY} | + | .sin_port = groupSockaddr.sin_port, |
| - | }; | + | .sin_addr = {INADDR_ANY} |
| - | res = bind(sockfd, | + | }; |
| - | if(res) error(1, errno, " | + | res = bind(sockfd, |
| - | + | if (res) | |
| - | // send IGMP join group | + | |
| - | ip_mreqn groupDescription{ | + | |
| - | .imr_multiaddr = groupSockaddr.sin_addr, | + | // send IGMP join group |
| - | .imr_address = {INADDR_ANY}, | + | ip_mreqn groupDescription{ |
| - | .imr_ifindex = 0 | + | .imr_multiaddr = groupSockaddr.sin_addr, |
| - | }; | + | .imr_address = {INADDR_ANY}, |
| - | auto ret = setsockopt(sockfd, | + | .imr_ifindex = 0 |
| - | if(ret) error(1, errno, " | + | }; |
| - | + | auto ret = setsockopt(sockfd, | |
| - | // handle ctrl+c for gracefull exit | + | if (ret) |
| - | setupSignals(); | + | |
| - | + | ||
| - | // receive and display ANY packet that arrives | + | // handle ctrl+c for gracefull exit |
| - | std:: | + | setupSignals(); |
| - | sockaddr_in peerAddr; | + | |
| - | socklen_t peerAddrSize; | + | // receive and display ANY packet that arrives |
| - | char buffer[255]; | + | std::thread readerThread([& |
| - | while(true){ | + | sockaddr_in peerAddr; |
| - | peerAddrSize = sizeof(peerAddr); | + | socklen_t peerAddrSize; |
| - | auto readSize = recvfrom(sockfd, | + | char buffer[255]; |
| - | if(quitting) break; | + | while (true) { |
| - | if(readSize==-1) error(1, | + | peerAddrSize = sizeof(peerAddr); |
| - | if(readSize> | + | auto readSize = recvfrom(sockfd, |
| - | buffer[readSize] = 0; | + | if (quitting) |
| - | printf("< | + | |
| - | } | + | if (readSize == -1) |
| - | }); | + | |
| - | + | if (readSize > 254) { | |
| - | // read standard input and send it to the group | + | |
| - | char buffer[255]; | + | |
| - | while(true){ | + | |
| - | auto readSize = read(0, buffer, 254); | + | buffer[readSize] = 0; |
| - | if(quitting || !readSize) break; | + | printf("< |
| - | if(readSize< | + | } |
| - | + | }); | |
| - | auto res = sendto(sockfd, | + | |
| - | if(res!=readSize) { error(0, | + | // read standard input and send it to the group |
| - | } | + | char buffer[255]; |
| - | + | while (true) { | |
| - | quitting = true; | + | auto readSize = read(0, buffer, 254); |
| - | // leave group | + | if (quitting || !readSize) |
| - | setsockopt(sockfd, | + | |
| - | // close socket AND interrupt all blocked recvfrom | + | if (readSize < 0) { |
| - | shutdown(sockfd, | + | |
| - | // wait for child | + | |
| - | readerThread.join(); | + | |
| - | + | ||
| - | return 0; | + | auto res = sendto(sockfd, |
| + | if (res != readSize) { | ||
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | quitting = true; | ||
| + | // leave group | ||
| + | setsockopt(sockfd, | ||
| + | // close socket AND interrupt all blocked recvfrom | ||
| + | shutdown(sockfd, | ||
| + | | ||
| + | | ||
| + | readerThread.join(); | ||
| + | |||
| + | return 0; | ||
| } | } | ||
| - | void setupSignals(){ | + | void setupSignals() { |
| - | struct sigaction action; | + | struct sigaction action; |
| - | + | ||
| - | // read sigint handler description | + | // read sigint handler description |
| - | auto res = sigaction(SIGINT, | + | auto res = sigaction(SIGINT, |
| - | if(res) error(1, errno, " | + | if (res) |
| - | + | | |
| - | // set new interrupt handler | + | |
| - | action.sa_handler = ctrl_c; | + | // set new interrupt handler |
| - | // disable SA_RESTART flag to exit blocking IO upon a signal | + | action.sa_handler = ctrl_c; |
| - | action.sa_flags &= ~SA_RESTART; | + | // disable SA_RESTART flag to exit blocking IO upon a signal |
| - | + | action.sa_flags &= ~SA_RESTART; | |
| - | // update sigint handler description | + | |
| - | res = sigaction(SIGINT, | + | // update sigint handler description |
| - | if(res) error(1, errno, " | + | res = sigaction(SIGINT, |
| + | if (res) | ||
| + | | ||
| } | } | ||
| </ | </ | ||
sk2/multicast_example.1479803883.txt.gz · Last modified: (external edit)