最简单的组播程序

最简单的组播程序

组播,
发送: 与普通udp 发送并无不同,除了sendto的对端地址是一个组播地址.
接受: 如果在同一台电脑上启用多个进程或线程接受,需要设置 SO_REUSEADDR 选项为1
    只要加入了组播组,就可以从中接受数据了.

下面是具体的代码, 是我从庞杂的代码中简化整理的.

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MULTICAST_ADDR "239.1.1.1"
#define MULTICAST_PORT 8888
//组播, 发送与普通udp 发送并无不同,除了sendto的对端地址是一个组播地址.
//sendit
int main(int argc, char **argv)
{
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
	if (sockfd < 0)
	{
		printf("socket creating error\n");
		exit(EXIT_FAILURE);
	}
	unsigned int socklen = sizeof(struct sockaddr_in);
	struct sockaddr_in peeraddr;
	memset(&peeraddr, 0, socklen);
	peeraddr.sin_family = AF_INET;
	peeraddr.sin_port = htons(MULTICAST_PORT);    
	if (inet_pton(AF_INET, MULTICAST_ADDR, &peeraddr.sin_addr) <= 0) {
		printf("wrong group address!\n");
		exit(EXIT_FAILURE);
	}
#define BUFLEN 255
	char recmsg[BUFLEN + 1];
	for (;;) {
		bzero(recmsg, BUFLEN + 1);
		printf("input message to send:");
		if (fgets(recmsg, BUFLEN, stdin) == (char *) EOF) 
			exit(EXIT_FAILURE);;
		if (sendto(sockfd, recmsg, strlen(recmsg), 0,(struct sockaddr *) &peeraddr,
					sizeof(struct sockaddr_in)) < 0)      
		{
			printf("sendto error!\n");
			exit(EXIT_FAILURE);;
		}
		printf("send message:%s", recmsg);  
	}
}
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>

//receive it
#define MULTICAST_ADDR "239.1.1.1"
#define MULTICAST_PORT 8888
//组播地址以239.1.1.1 为例.
int main(int argc, char **argv)
{

	//1.创建socket
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd < 0) 
	{
		printf("socket creating err in udptalk\n");
		exit(EXIT_FAILURE);
	}

	//设置sock可选项, 可重复使用地址
	unsigned int yes = 1;
	if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) 
	{
		perror("Reusing ADDR failed");
		exit(1);
	}

	//receive message 需要先bind socket, 说明从哪个地址,哪个端口接受. send 则不需要
	struct sockaddr_in myaddr;
	unsigned int socklen = sizeof(struct sockaddr_in);
	memset(&myaddr, 0, socklen);
	myaddr.sin_family = AF_INET;
	myaddr.sin_port = htons(MULTICAST_PORT);
	inet_pton(AF_INET, MULTICAST_ADDR, &myaddr.sin_addr);

	if (bind(sockfd, (struct sockaddr *) &myaddr,sizeof(struct sockaddr_in)) == -1) 
	{
		printf("Bind error\n");
		exit(EXIT_FAILURE);
	}

	//设置sock可选项,将当前sock加入到组播组
	struct ip_mreq mreq;
	bzero(&mreq, sizeof(struct ip_mreq));
	inet_pton(AF_INET, MULTICAST_ADDR, &mreq.imr_multiaddr.s_addr);
	if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,sizeof(struct ip_mreq)) == -1) 
	{
		perror("setsockopt");
		exit(EXIT_FAILURE);
	}


	#define BUFLEN 255
	char recmsg[BUFLEN + 1];
	unsigned int n;
	struct sockaddr_in peeraddr;
	for (;;) 
	{
		bzero(recmsg, BUFLEN + 1);
		printf("waiting messge ... \n");
		n = recvfrom(sockfd, recmsg, BUFLEN, 0,(struct sockaddr *) &peeraddr, &socklen);
		if (n < 0) 
		{
			printf("recvfrom err!\n");
			exit(EXIT_FAILURE);
		} 
		else 
		{

			recmsg[n] = 0;
			printf("peer:%s", recmsg);
		}
	}
}

执行结果. 给一张图片参考.

可以修改代码,打印出对端的ip 地址和端口号。

 printf("peer:%s \nfrom addr:0x%x,port:%d\n", recmsg,ntohl(peeraddr.sin_addr.s_addr),ntohs(peeraddr.sin_port));

也可以用 inet_ntop 把对端地址转换成字符串.inet_ntop(AF_INET,&peeraddr.sin_addr,ipStr,sizeof(ipStr));

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值