// // Simple listener.c program for UDP multicast // // Adapted from: // http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/example.html // // Changes: // * Compiles for Windows as well as Linux // * Takes the port and group on the command line // #ifdef _WIN32 #include // before Windows.h, else Winsock 1 conflict #include // needed for ip_mreq definition for multicast #include #pragma comment(lib,"ws2_32.lib") #else #include #include #include #include #include #endif #include #include #include #define MSGBUFSIZE 256 void PrintError(char *msg,DWORD err) { if(msg) fprintf(stderr,"%s%d\n",msg,err); //DWORD err = GetLastError(); LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL); fprintf(stderr,"WIN Last Error: %s" , (LPCTSTR)lpMsgBuf); // Free the buffer. LocalFree( lpMsgBuf ); } int main(int argc, char *argv[]) { if (argc != 3) { printf("Command line args should be multicast group and port\n"); printf("(e.g. for SSDP, `listener 239.255.255.250 1900`)\n"); return 1; } char* group = argv[1]; // e.g. 239.255.255.250 for SSDP int port = atoi(argv[2]); // 0 if error, which is an invalid port #ifdef _WIN32 // // Initialize Windows Socket API with given VERSION. // WSADATA wsaData; if (WSAStartup(0x0101, &wsaData)) { perror("WSAStartup"); return 1; } #endif // create what looks like an ordinary UDP socket // int fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); return 1; } // allow multiple sockets to use the same PORT number // u_int yes = 1; if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (char*) &yes, sizeof(yes) ) < 0 ){ perror("Reusing ADDR failed"); return 1; } // set up destination address // struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); // differs from sender addr.sin_port = htons(port); // bind to receive address // int iRet; iRet=bind(fd, (struct sockaddr*) &addr, sizeof(addr)); if ( iRet < 0) { PrintError("bind",iRet); return 1; } // use setsockopt() to request that the kernel join a multicast group // struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(group); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if ( setsockopt( fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mreq, sizeof(mreq) ) < 0 ){ perror("setsockopt"); return 1; } // now just enter a read-print loop // while (1) { char msgbuf[MSGBUFSIZE]; int addrlen = sizeof(addr); int nbytes = recvfrom( fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *) &addr, &addrlen ); if (nbytes < 0) { perror("recvfrom"); return 1; } msgbuf[nbytes] = '\0'; puts(msgbuf); } #ifdef _WIN32 // // Program never actually gets here due to infinite loop that has to be // canceled, but since people on the internet wind up using examples // they find at random in their own code it's good to show what shutting // down cleanly would look like. // WSACleanup(); #endif return 0; }