Tools for multicast testing (msend and mreceive) https://github.com/troglobit/mtools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mreceive.c 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * mreceive.c -- Prints UDP messages received from a multicast group.
  3. *
  4. * (c) Jianping Wang, Yvan Pointurier, Jorg Liebeherr, 2002
  5. * Multimedia Networks Group, University of Virginia
  6. *
  7. * SOURCE CODE RELEASED TO THE PUBLIC DOMAIN
  8. *
  9. * version 2.0 - 5/20/2002
  10. * version 2.1 - 12/4/2002
  11. * Update version display.
  12. * version 2.2 - 05/17/2003
  13. * Assign default values to parameters . The usage information is
  14. * changed according to README_mreceive.txt
  15. *
  16. * Based on this public domain program:
  17. * u_mctest.c (c) Bob Quinn 2/4/97
  18. *
  19. */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <arpa/inet.h>
  27. #include <sys/time.h>
  28. #define TRUE 1
  29. #define FALSE 0
  30. #ifndef INVALID_SOCKET
  31. #define INVALID_SOCKET -1
  32. #endif
  33. #ifndef SOCKET_ERROR
  34. #define SOCKET_ERROR -1
  35. #endif
  36. #define BUFSIZE 1024
  37. #define TTL_VALUE 2
  38. #define LOOPMAX 20
  39. #define MAXIP 16
  40. char *TEST_ADDR = "224.1.1.1";
  41. int TEST_PORT = 4444;
  42. unsigned long IP[MAXIP];
  43. int NUM = 0;
  44. void printHelp(void)
  45. {
  46. printf("mreceive version %s\n\
  47. Usage: mreceive [-g GROUP] [-p PORT] [-i ADDRESS ] ... [-i ADDRESS] [-n]\n\
  48. mreceive [-v | -h]\n\
  49. \n\
  50. -g GROUP IP multicast group address to listen to. Default: 224.1.1.1\n\
  51. -p PORT UDP port number used in the multicast packets. Default: 4444\n\
  52. -i ADDRESS IP addresses of one or more interfaces to listen for the given\n\
  53. multicast group. Default: the system default interface.\n\
  54. -n Interpret the contents of the message as a number instead of\n\
  55. a string of characters. Use this with `msend -n`\n\
  56. -v Print version information.\n\
  57. -h Print the command usage.\n\n", VERSION);
  58. }
  59. int main(int argc, char *argv[])
  60. {
  61. struct sockaddr_in stLocal, stFrom;
  62. unsigned char achIn[BUFSIZE];
  63. int s, i;
  64. struct ip_mreq stMreq;
  65. int iTmp, iRet;
  66. int ipnum = 0;
  67. int ii;
  68. unsigned int numreceived;
  69. int rcvCountOld = 0;
  70. int rcvCountNew = 1;
  71. int starttime;
  72. int curtime;
  73. struct timeval tv;
  74. /*
  75. if( argc < 2 ) {
  76. printHelp();
  77. return 1;
  78. }
  79. */
  80. ii = 1;
  81. if ((argc == 2) && (strcmp(argv[ii], "-v") == 0)) {
  82. printf("mreceive version 2.2\n");
  83. return 0;
  84. }
  85. if ((argc == 2) && (strcmp(argv[ii], "-h") == 0)) {
  86. printHelp();
  87. return 0;
  88. }
  89. while (ii < argc) {
  90. if (strcmp(argv[ii], "-g") == 0) {
  91. ii++;
  92. if ((ii < argc) && !(strchr(argv[ii], '-'))) {
  93. TEST_ADDR = argv[ii];
  94. ii++;
  95. }
  96. } else if (strcmp(argv[ii], "-p") == 0) {
  97. ii++;
  98. if ((ii < argc) && !(strchr(argv[ii], '-'))) {
  99. TEST_PORT = atoi(argv[ii]);
  100. ii++;
  101. }
  102. } else if (strcmp(argv[ii], "-i") == 0) {
  103. ii++;
  104. if ((ii < argc) && !(strchr(argv[ii], '-'))) {
  105. IP[ipnum] = inet_addr(argv[ii]);
  106. ii++;
  107. ipnum++;
  108. }
  109. } else if (strcmp(argv[ii], "-n") == 0) {
  110. ii++;
  111. NUM = 1;
  112. } else {
  113. printf("wrong parameters!\n\n");
  114. printHelp();
  115. return 1;
  116. }
  117. }
  118. /* get a datagram socket */
  119. s = socket(AF_INET, SOCK_DGRAM, 0);
  120. if (s == INVALID_SOCKET) {
  121. printf("socket() failed.\n");
  122. exit(1);
  123. }
  124. /* avoid EADDRINUSE error on bind() */
  125. iTmp = TRUE;
  126. iRet = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&iTmp, sizeof(iTmp));
  127. if (iRet == SOCKET_ERROR) {
  128. printf("setsockopt() SO_REUSEADDR failed.\n");
  129. exit(1);
  130. }
  131. /* name the socket */
  132. stLocal.sin_family = AF_INET;
  133. stLocal.sin_addr.s_addr = htonl(INADDR_ANY);
  134. stLocal.sin_port = htons(TEST_PORT);
  135. iRet = bind(s, (struct sockaddr *)&stLocal, sizeof(stLocal));
  136. if (iRet == SOCKET_ERROR) {
  137. printf("bind() failed.\n");
  138. exit(1);
  139. }
  140. /* join the multicast group. */
  141. if (!ipnum) { /* single interface */
  142. stMreq.imr_multiaddr.s_addr = inet_addr(TEST_ADDR);
  143. stMreq.imr_interface.s_addr = INADDR_ANY;
  144. iRet = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
  145. if (iRet == SOCKET_ERROR) {
  146. printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
  147. exit(1);
  148. }
  149. } else {
  150. for (i = 0; i < ipnum; i++) {
  151. stMreq.imr_multiaddr.s_addr = inet_addr(TEST_ADDR);
  152. stMreq.imr_interface.s_addr = IP[i];
  153. iRet = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
  154. if (iRet == SOCKET_ERROR) {
  155. printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
  156. exit(1);
  157. }
  158. }
  159. }
  160. /* set TTL to traverse up to multiple routers */
  161. iTmp = TTL_VALUE;
  162. iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&iTmp, sizeof(iTmp));
  163. if (iRet == SOCKET_ERROR) {
  164. printf("setsockopt() IP_MULTICAST_TTL failed.\n");
  165. exit(1);
  166. }
  167. /* disable loopback */
  168. /* iTmp = TRUE; */
  169. iTmp = FALSE;
  170. iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&iTmp, sizeof(iTmp));
  171. if (iRet == SOCKET_ERROR) {
  172. printf("setsockopt() IP_MULTICAST_LOOP failed.\n");
  173. exit(1);
  174. }
  175. printf("Now receiving from multicast group: %s\n", TEST_ADDR);
  176. for (i = 0;; i++) {
  177. socklen_t addr_size = sizeof(struct sockaddr_in);
  178. static int iCounter = 1;
  179. /* receive from the multicast address */
  180. iRet = recvfrom(s, achIn, BUFSIZE, 0, (struct sockaddr *)&stFrom, &addr_size);
  181. if (iRet < 0) {
  182. printf("recvfrom() failed.\n");
  183. exit(1);
  184. }
  185. if (NUM) {
  186. gettimeofday(&tv, NULL);
  187. if (i == 0)
  188. starttime = tv.tv_sec * 1000000 + tv.tv_usec;
  189. curtime = tv.tv_sec * 1000000 + tv.tv_usec - starttime;
  190. numreceived =
  191. (unsigned int)achIn[0] + ((unsigned int)(achIn[1]) << 8) + ((unsigned int)(achIn[2]) << 16) +
  192. ((unsigned int)(achIn[3]) >> 24);
  193. fprintf(stdout, "%5d\t%s:%5d\t%d.%03d\t%5d\n", iCounter, inet_ntoa(stFrom.sin_addr), ntohs(stFrom.sin_port),
  194. curtime / 1000000, (curtime % 1000000) / 1000, numreceived);
  195. fflush(stdout);
  196. rcvCountNew = numreceived;
  197. if (rcvCountNew > rcvCountOld + 1) {
  198. if (rcvCountOld + 1 == rcvCountNew - 1)
  199. printf("****************\nMessage not received: %d\n****************\n", rcvCountOld + 1);
  200. else
  201. printf("****************\nMessages not received: %d to %d\n****************\n",
  202. rcvCountOld + 1, rcvCountNew - 1);
  203. }
  204. if (rcvCountNew == rcvCountOld) {
  205. printf("Duplicate message received: %d\n", rcvCountNew);
  206. }
  207. if (rcvCountNew < rcvCountOld) {
  208. printf("****************\nGap detected: %d from %d\n****************\n", rcvCountNew, rcvCountOld);
  209. }
  210. rcvCountOld = rcvCountNew;
  211. } else {
  212. printf("Receive msg %d from %s:%d: %s\n",
  213. iCounter, inet_ntoa(stFrom.sin_addr), ntohs(stFrom.sin_port), achIn);
  214. }
  215. iCounter++;
  216. }
  217. return 0;
  218. } /* end main() */
  219. /**
  220. * Local Variables:
  221. * version-control: t
  222. * indent-tabs-mode: t
  223. * c-file-style: "linux"
  224. * End:
  225. */