#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <thread>
#include <signal.h>
#include <cstring>
#include <iostream>
#include <sstream>
const char HELLO_GROUP[] = "225.0.0.37";
const int HELLO_PORT = 12345;
static volatile bool keepRunning = true;
void usage(const char* progname)
{
printf("Usage:\n %s [<mcast_group> <port> [TTL]]\nNote: TTL = 0-255\n", progname);
printf("Example:\n %s %s %d 1\n", progname, HELLO_GROUP, HELLO_PORT);
}
void sigIntHandler(int)
{
printf("Got SIGINT (Ctrl+C). Quitting...\n");
keepRunning = false;
}
void sigTermHandler(int)
{
printf("Got SIGTERM. Cleaning up. Quitting...\n");
keepRunning = false;
}
void sigHupHandler(int)
{
printf("Got SIGHUP. Ignoring.\n");
}
std::ostream& operator<< (std::ostream& ostr, const std::chrono::time_point<std::chrono::system_clock>& tp)
{
std::time_t ttp = std::chrono::system_clock::to_time_t(tp);
ostr << std::ctime(&ttp);
return ostr;
}
int main(int argc, const char* argv[])
{
// Handle Ctrl+C and quit gracefully
signal(SIGINT, sigIntHandler);
// Handle SIGTERM (15) and quit gracefully
signal(SIGTERM, sigTermHandler);
// Handle SIGHUP: Ignore
signal(SIGHUP, sigHupHandler);
if (argc != 3 && argc != 4)
{
usage(argv[0]);
exit(0);
}
const char* mcastGroup = argv[1];
int portNum = std::atoi(argv[2]);
unsigned char ttl = static_cast<unsigned char>(std::atoi(argv[3]));
struct sockaddr_in addr;
int fd;
//struct ip_mreq mreq;
const char helloMsg[] = "Hello, World!";
const char byeMsg[] = "Goodbye!";
// Create a UDP socket
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(1);
}
// Set up destination address
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(mcastGroup);
addr.sin_port = htons(portNum);
// Set up multicast TTL
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
{
perror("Could not set multicast TTL");
exit(1);
}
// Keep sending until get a signal to terminate
while (keepRunning)
{
std::ostringstream osstr;
osstr << helloMsg << ": " << std::chrono::system_clock::now();
if (sendto(fd, osstr.str().c_str(), osstr.str().size(), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
perror("sendto helloMsg");
exit(1);
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// Say goodbye
std::ostringstream osstr;
osstr << byeMsg << ": " << std::chrono::system_clock::now();
if (sendto(fd, osstr.str().c_str(), osstr.str().size(), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
perror("sendto byeMsg");
exit(1);
}
return 0;
}