#include #include #include #include #ifdef WIN32 #include #else #include #include #include #include #include #endif #define BUFSZ 512 #define MULTICAST_PORT 7766 #define MULTICAST_GROUP "239.0.0.1" #define RECEIVE_IP_ADDR "128.127.58.113" #define TRANSMIT_IP_ADDR "128.127.58.112" #define USE_RECV_ADDR /** * socket creation function. * this function will create a multicast socket for reading or writing. * @param[out] sock: structure sockaddr_in used in recv/sendto functions * @param[in] type: type of socket: 'r' for reading, 'w' for writing * @return a opened socket. Exit program on error (exit() called) */ int socket_init(struct sockaddr_in *sock, char type) { struct ip_mreq imr; int sd; unsigned char ttl = 1; struct in_addr If; /* create socket */ sd = socket(PF_INET, SOCK_DGRAM, 0); if (sd < 0) { perror("socket"); exit(EXIT_FAILURE); } /* initialize sock descriptor */ memset(sock, 0, sizeof(struct sockaddr_in)); switch (type) { case 'r': /* receive mode */ sock->sin_family = AF_INET; sock->sin_port = htons(MULTICAST_PORT); #ifdef USE_RECV_ADDR sock->sin_addr.s_addr = inet_addr(RECEIVE_IP_ADDR); #else sock->sin_addr.s_addr = htonl(INADDR_ANY); #endif if (bind(sd, (struct sockaddr *) sock, sizeof(struct sockaddr_in)) < 0) { perror("bind"); exit(1); } If.s_addr = inet_addr(RECEIVE_IP_ADDR); if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char*)&If, sizeof(If))) { perror("IP_MULTICAST_IF"); exit(1); } /* multicast group to join */ imr.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP); /* interface to read on */ imr.imr_interface.s_addr = inet_addr(RECEIVE_IP_ADDR); /* set GROUP option */ if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *) &imr, sizeof(struct ip_mreq)) < 0) { perror("setsockopt: IP_ADD_MEMBERSHIP"); exit(1); } /* enable multicast */ if (0 != setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl))) { perror("setsockopt"); exit(1); } break; case 'w': /* transmission mode */ sock->sin_family = AF_INET; sock->sin_port = 0; sock->sin_addr.s_addr = inet_addr(TRANSMIT_IP_ADDR); if (bind(sd, (struct sockaddr *) sock, sizeof(struct sockaddr_in)) < 0) { perror("bind"); exit(1); } sock->sin_family = AF_INET; sock->sin_port = htons(MULTICAST_PORT); sock->sin_addr.s_addr = inet_addr(MULTICAST_GROUP); /* enable multicast */ if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) { perror("setsockopt: IP_MULTICAST_TTL"); exit(EXIT_FAILURE); } break; default: printf("socket_init: unknown type /%c/\n", type); exit(EXIT_FAILURE); } return sd; } void m_receive(void) { struct sockaddr_in from; unsigned int len = sizeof(from); /* create the reception socket */ int sd = socket_init(&from, 'r'); int cnt; char buf[BUFSZ]; /* infinite loop */ while (1) {/* try to receive from socket */ cnt = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *) &from, &len); if (cnt < 0) {/* something bad happened, quit */ perror("recvfrom"); exit(1); } else if (cnt == 0) {/* socket closed (udp should never goes here) exit while loop */ break; } /* all goes right, write the received message */ buf[cnt] = 0; printf("%s\n", buf); } printf("m_receive: done\n"); } /** * transmission function. * @param buf: message to send. */ void m_send(const char *buf) { struct sockaddr_in to; /* create the transmission socket */ int sd = socket_init(&to, 'w'); int cnt; /* send the message (just like we whoumd have done with regular socket */ cnt = sendto(sd, buf, strlen(buf), 0, (struct sockaddr *) &to, sizeof(to)); if (cnt < 0) { perror("sendto"); exit(1); } } /** usage : * cmd.exe r * cmd.exe w message */ void usage(const char *name) { printf("usage :\n\n"); printf("reception mode\n"); printf("\t %s r\n\n", name); printf("transmission mode\n"); printf("\t %s w message to send\n", name); } /** * Application entry point */ int main(int argc, char **argv) { #ifdef WIN32 WSADATA wsaData; int ret = WSAStartup(MAKEWORD(2, 2), &wsaData); if (ret != 0) { printf("WSAStartup failed: %d\n", ret); return 1; } #endif if (argc < 2) { usage(*argv); } else { switch (*argv[1]) { case 'r': /* go in receive mode */ m_receive(); break; case 'w': /* note that this method is not optimized : we create a socket of each word of the message to send. */ { int i; for (i = 2; i != argc; ++i) {/* send each parameter given to program*/ m_send(argv[i]); } } break; default: usage(*argv); break; } } #ifdef WIN32 WSACleanup(); #endif return 0; }