Subject: Re: multicast
To: Robert Dobbs <banshee@gabriella.resort.com>
From: Francis Dupont <Francis.Dupont@inria.fr>
List: current-users
Date: 06/06/1995 13:25:54
 In your previous mail you wrote:
   
   Does anyone have some small sample code which uses multicasting?
   
=> I have a pair of small programs for multicast testing:

-------------------------------- in2multi.c --------------------------------
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

struct sockaddr_in msin;

main(argc, argv)
	int             argc;
	char          **argv;
{
	unsigned char   ttl;
	int             s, cc, ch;
	char            buf[1024];
	u_long          addr;
	extern char	*optarg;
	extern int	optind;

	ttl = 0;
	addr = htonl(INADDR_ANY);
	if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
		perror("socket");
		exit(1);
	}
	while ((ch = getopt(argc, argv, "t:i:")) != -1)
		switch(ch) {
		    case 't':
			ttl = atoi(optarg);
			break;
		    case 'i':
			addr = htonl(inet_addr(optarg));
			break;
		}
	argc -= optind;
	argv += optind;
	if (argc != 1) {
		fprintf(stderr, "groupe manque\n");
		exit(-1);
	}
	if (ttl > 0)
		if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
			       &ttl, sizeof(ttl)) < 0) {
			perror("setsockopt IP_MULTICAST_TTL");
			return (0);
		}
	if (addr != htonl(INADDR_ANY))
		if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
			       &addr, sizeof(addr)) < 0) {
			perror("setsockopt IP_MULTICAST_IF");
			return(0);
		}

	addr = inet_addr(*argv);

	msin.sin_family = AF_INET;
	msin.sin_addr.s_addr = htonl(addr);
	msin.sin_port = htons(54321);

	for (;;) {
		cc = read(0, buf, 1024);
		if (cc < 0) {
			perror("read file");
			return (cc);
		} else if (cc > 0) {
			if (sendto(s, buf, cc, 0,
				   (struct sockaddr *)&msin, sizeof(msin)) < 0)
				perror("sendto");
			fprintf(stderr, "-%d->\n", cc);
		} else {
			fprintf(stderr, ".\n", cc);
			return (0);
		}
	}
}
-------------------------------- multi2out.c --------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

struct sockaddr_in msin;
int s;

#define  IPPORT 54321

Error(c, s)
	char           *c;
	int             s;
{
	perror(c);
	close(s);
	exit(1);
}

void BrokenPipe(Signal, Code, SignalContextPtr)
	int             Signal, Code;
	struct sigcontext *SignalContextPtr;
{
	signal(SIGPIPE, BrokenPipe);
	return;
}

main(argc, argv)
	int             argc;
	char           *argv[];
{
	struct ip_mreq  mreq;
	int             cc, ccb, ch;
	char            buf[10240];
	int             len;
	int             one = 1;
	extern char	*optarg;
	extern int	optind;

	mreq.imr_interface.s_addr = INADDR_ANY;
	signal(SIGPIPE, BrokenPipe);
	while ((ch = getopt(argc, argv, "i:")) != -1)
		switch(ch) {
		    case 'i':
			mreq.imr_interface.s_addr = htonl(inet_addr(optarg));
			break;
		}
	argc -= optind;
	argv += optind;
	if (argc != 1) {
		fprintf(stderr, "groupe manque\n");
		exit(-1);
	}
	if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
		perror("socket");
		exit(1);
	}
	(void) setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));

	msin.sin_family = AF_INET;
	msin.sin_port = htons(IPPORT);
	if (bind(s, (struct sockaddr *)&msin, sizeof(msin)) < 0) {
		perror("bind");
		exit(1);
	}

	mreq.imr_multiaddr.s_addr = htonl(inet_addr(*argv));
	if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
		       &mreq, sizeof(mreq)) < 0) {
		perror("setsockopt IP_ADD_MEMBERSHIP");
		return (0);
	}
	for (;;) {
		cc = read(s, buf, 10240);
		if (cc < 0) {
			perror("read socket");
			return (cc);
		} else if (cc > 0) {
			ccb = write(1, buf, cc);
			if (ccb != cc)
				perror("write file");
			fprintf(stderr, "<-%d-\n", cc);
		} else {
			fprintf(stderr, "..\n");
			return (0);
		}
	}
}
-------------------------------- end --------------------------------

It is difficult to make them simpler... Please add your code
if you need more (for instance IP_MULTICAST_LOOP option).
Beware: multi2out can't detect the end of input.

Francis.Dupont@inria.fr