|
- /*
- * mreceive.c -- Prints UDP messages received from a multicast group.
- *
- * (c) Jianping Wang, Yvan Pointurier, Jorg Liebeherr, 2002
- * Multimedia Networks Group, University of Virginia
- *
- * SOURCE CODE RELEASED TO THE PUBLIC DOMAIN
- *
- * version 2.0 - 5/20/2002
- * version 2.1 - 12/4/2002
- * Update version display.
- * version 2.2 - 05/17/2003
- * Assign default values to parameters . The usage information is
- * changed according to README_mreceive.txt
- *
- * Based on this public domain program:
- * u_mctest.c (c) Bob Quinn 2/4/97
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/time.h>
-
- #define TRUE 1
- #define FALSE 0
- #ifndef INVALID_SOCKET
- #define INVALID_SOCKET -1
- #endif
- #ifndef SOCKET_ERROR
- #define SOCKET_ERROR -1
- #endif
- #define BUFSIZE 1024
- #define TTL_VALUE 2
- #define LOOPMAX 20
- #define MAXIP 16
-
- char *TEST_ADDR = "224.1.1.1";
- int TEST_PORT = 4444;
- unsigned long IP[MAXIP];
- int NUM = 0;
-
- void printHelp(void)
- {
- printf("mreceive version %s\n\
- Usage: mreceive [-g GROUP] [-p PORT] [-i ADDRESS ] ... [-i ADDRESS] [-n]\n\
- mreceive [-v | -h]\n\
- \n\
- -g GROUP IP multicast group address to listen to. Default: 224.1.1.1\n\
- -p PORT UDP port number used in the multicast packets. Default: 4444\n\
- -i ADDRESS IP addresses of one or more interfaces to listen for the given\n\
- multicast group. Default: the system default interface.\n\
- -n Interpret the contents of the message as a number instead of\n\
- a string of characters. Use this with `msend -n`\n\
- -v Print version information.\n\
- -h Print the command usage.\n\n", VERSION);
- }
-
- int main(int argc, char *argv[])
- {
- struct sockaddr_in stLocal, stFrom;
- unsigned char achIn[BUFSIZE];
- int s, i;
- struct ip_mreq stMreq;
- int iTmp, iRet;
- int ipnum = 0;
- int ii;
- unsigned int numreceived;
- int rcvCountOld = 0;
- int rcvCountNew = 1;
- int starttime;
- int curtime;
- struct timeval tv;
-
- /*
- if( argc < 2 ) {
- printHelp();
- return 1;
- }
- */
-
- ii = 1;
-
- if ((argc == 2) && (strcmp(argv[ii], "-v") == 0)) {
- printf("mreceive version 2.2\n");
- return 0;
- }
- if ((argc == 2) && (strcmp(argv[ii], "-h") == 0)) {
- printHelp();
- return 0;
- }
-
-
- while (ii < argc) {
- if (strcmp(argv[ii], "-g") == 0) {
- ii++;
- if ((ii < argc) && !(strchr(argv[ii], '-'))) {
- TEST_ADDR = argv[ii];
- ii++;
- }
- } else if (strcmp(argv[ii], "-p") == 0) {
- ii++;
- if ((ii < argc) && !(strchr(argv[ii], '-'))) {
- TEST_PORT = atoi(argv[ii]);
- ii++;
- }
- } else if (strcmp(argv[ii], "-i") == 0) {
- ii++;
- if ((ii < argc) && !(strchr(argv[ii], '-'))) {
- IP[ipnum] = inet_addr(argv[ii]);
- ii++;
- ipnum++;
- }
- } else if (strcmp(argv[ii], "-n") == 0) {
- ii++;
- NUM = 1;
- } else {
- printf("wrong parameters!\n\n");
- printHelp();
- return 1;
- }
- }
-
- /* get a datagram socket */
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s == INVALID_SOCKET) {
- printf("socket() failed.\n");
- exit(1);
- }
-
- /* avoid EADDRINUSE error on bind() */
- iTmp = TRUE;
- iRet = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&iTmp, sizeof(iTmp));
- if (iRet == SOCKET_ERROR) {
- printf("setsockopt() SO_REUSEADDR failed.\n");
- exit(1);
- }
-
- /* name the socket */
- stLocal.sin_family = AF_INET;
- stLocal.sin_addr.s_addr = htonl(INADDR_ANY);
- stLocal.sin_port = htons(TEST_PORT);
- iRet = bind(s, (struct sockaddr *)&stLocal, sizeof(stLocal));
- if (iRet == SOCKET_ERROR) {
- printf("bind() failed.\n");
- exit(1);
- }
-
- /* join the multicast group. */
- if (!ipnum) { /* single interface */
- stMreq.imr_multiaddr.s_addr = inet_addr(TEST_ADDR);
- stMreq.imr_interface.s_addr = INADDR_ANY;
- iRet = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
- if (iRet == SOCKET_ERROR) {
- printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
- exit(1);
- }
- } else {
- for (i = 0; i < ipnum; i++) {
- stMreq.imr_multiaddr.s_addr = inet_addr(TEST_ADDR);
- stMreq.imr_interface.s_addr = IP[i];
- iRet = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
- if (iRet == SOCKET_ERROR) {
- printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
- exit(1);
- }
- }
- }
-
- /* set TTL to traverse up to multiple routers */
- iTmp = TTL_VALUE;
- iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&iTmp, sizeof(iTmp));
- if (iRet == SOCKET_ERROR) {
- printf("setsockopt() IP_MULTICAST_TTL failed.\n");
- exit(1);
- }
-
- /* disable loopback */
- /* iTmp = TRUE; */
- iTmp = FALSE;
- iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&iTmp, sizeof(iTmp));
- if (iRet == SOCKET_ERROR) {
- printf("setsockopt() IP_MULTICAST_LOOP failed.\n");
- exit(1);
- }
-
- printf("Now receiving from multicast group: %s\n", TEST_ADDR);
-
- for (i = 0;; i++) {
- socklen_t addr_size = sizeof(struct sockaddr_in);
- static int iCounter = 1;
-
- /* receive from the multicast address */
-
- iRet = recvfrom(s, achIn, BUFSIZE, 0, (struct sockaddr *)&stFrom, &addr_size);
- if (iRet < 0) {
- printf("recvfrom() failed.\n");
- exit(1);
- }
-
- if (NUM) {
- gettimeofday(&tv, NULL);
-
- if (i == 0)
- starttime = tv.tv_sec * 1000000 + tv.tv_usec;
- curtime = tv.tv_sec * 1000000 + tv.tv_usec - starttime;
- numreceived =
- (unsigned int)achIn[0] + ((unsigned int)(achIn[1]) << 8) + ((unsigned int)(achIn[2]) << 16) +
- ((unsigned int)(achIn[3]) >> 24);
- fprintf(stdout, "%5d\t%s:%5d\t%d.%03d\t%5d\n", iCounter, inet_ntoa(stFrom.sin_addr), ntohs(stFrom.sin_port),
- curtime / 1000000, (curtime % 1000000) / 1000, numreceived);
- fflush(stdout);
- rcvCountNew = numreceived;
- if (rcvCountNew > rcvCountOld + 1) {
- if (rcvCountOld + 1 == rcvCountNew - 1)
- printf("****************\nMessage not received: %d\n****************\n", rcvCountOld + 1);
- else
- printf("****************\nMessages not received: %d to %d\n****************\n",
- rcvCountOld + 1, rcvCountNew - 1);
- }
- if (rcvCountNew == rcvCountOld) {
- printf("Duplicate message received: %d\n", rcvCountNew);
- }
- if (rcvCountNew < rcvCountOld) {
- printf("****************\nGap detected: %d from %d\n****************\n", rcvCountNew, rcvCountOld);
- }
- rcvCountOld = rcvCountNew;
- } else {
- printf("Receive msg %d from %s:%d: %s\n",
- iCounter, inet_ntoa(stFrom.sin_addr), ntohs(stFrom.sin_port), achIn);
- }
- iCounter++;
- }
-
- return 0;
- } /* end main() */
-
- /**
- * Local Variables:
- * version-control: t
- * indent-tabs-mode: t
- * c-file-style: "linux"
- * End:
- */
|