1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
| /**
* petit programme multicast UDP.
* ce programme peut
* soit envoyer un message sur un groupe multicast,
* soit se mettre en écoute du même groupe et afficher les message reçus.
* testé avec cygwin et codegear2009 (c++builder) avec xp et vista.
* *devrait* fonctionner sous VC++ et unixoides.
* si compilé sous Visual / borland, WIN32 doit être défini
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef WIN32
#include <Winsock2.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
#ifdef __BORLANDC__
#pragma link "Ws2_32.lib"
#else
#pragma comment(lib, "Ws2_32.lib")
#endif
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
# define BUFSZ 512
# define MULTICAST_PORT 7766
# define MULTICAST_GROUP "224.0.0.1"
/**
* 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)
{
int sd;
unsigned char ttl = 1;
/* 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) {
/* receive mode */
case 'r':
sock->sin_family = AF_INET;
sock->sin_port = htons(MULTICAST_PORT);
sock->sin_addr.s_addr = htonl(INADDR_ANY);
/* bind */
if (bind(sd, (struct sockaddr *) sock, sizeof(struct sockaddr_in))
< 0) {
perror("bind");
exit(1);
}
/* enable multicast */
{
struct ip_mreq imr;
imr.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP); /* multicast group to join */
imr.imr_interface.s_addr = htonl(INADDR_ANY); /* interface to read on */
/* 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;
/* transmission mode */
case 'w':
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;
socklen_t 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;
int len = sizeof(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, len);
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);
}
}
#ifdef WIN32
WSACleanup();
#endif
return 0;
} |
Partager