组播通信应用示例,组播相较于广播是有一定区别的,他们之间的区别是,组播只能是在一组之内的主机能够接收到信息,对广播来说没那么广泛,是特定一个小组能够相互接收和传递。在对比MAC地址时,如果是目标组的话才能接收数据包,即将数据包交给OS处理处理,即IP层、否则丢弃(不接受)。

UDP组播通信代码如下:

因为涉及到组的问题,我们有两个形参,组号和自己的IP地址,接收端也需要两个形参,组号和IP地址 。

setsockopt(sockfd,IPPROTO_IP,IP_ADD_membership.&mreq,sizeof(struct ip_mreq));

Android udp 组播demo udp组播代码_Android udp 组播demo


发送端源代码:

#include<stdio.h>
 #include<stdlib.h>
 #include<sys/types.h>
 #include<sys/socket.h>
 #include<arpa/inet.h>
 #include<string.h>
 #define BUFLEN 255
 int main(int argc,char *argv[])
 {
 struct sockaddr_in peeraddr,myaddr;
 int sockft;
 char recmsg[BUFLEN+1];
 unsigned int socklen;
 sockft=socket(AF_INET,SOCK_DGRAM,0); //以UDP方式创建socket对象
 if(sockft<0)
 {
 printf(“socket creating error\n”);
 exit(EXIT_FAILURE);
 }
 socklen=sizeof(struct sockaddr_in);
 memset(&peeraddr,0,socklen);
 peeraddr.sin_family=AF_INET;
 peeraddr.sin_port=htons(7838); //初始化目的端口地址
 if(argv[1]) //从argv[]中读取发送的目的地址,显示是一个组播地址
 {
 if(inet_pton(AF_INET,argv[1],&peeraddr.sin_addr)<=0)
 {
 printf(“wrong group address!\n”);
 exit(EXIT_FAILURE);
 }
 }
 else
 {
 printf(“nogroup address!\n”);
 exit(EXIT_FAILURE);
 }
 memset(&myaddr,0,socklen);
 myaddr.sin_family=AF_INET;
 myaddr.sin_port=htons(23456); //绑定本机端口
 if(argv[2]) //获取本机绑定IP地址,既本机IP地址
 {
 if(inet_pton(AF_INET,argv[2],&myaddr.sin_addr)<=0)
 {
 printf(“self ip address error!\n”);
 exit(EXIT_FAILURE);
 }
 }
 else
 myaddr.sin_addr.s_addr=INADDR_ANY;
 if(bind(sockft,(struct sockaddr )&myaddr,sizeof(struct sockaddr_in))-1) //绑定本机ip地址
 {
 printf(“Bind error!\n”);
 exit(EXIT_FAILURE);
 }
 for(;😉
 {
 bzero(recmsg,BUFLEN+1);
 printf(“input message to send:”);
 if(fgets(recmsg,BUFLEN,stdin)(char)EOF) //从键盘中读取一行字符
 exit(EXIT_FAILURE);
 if(sendto(sockft,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<stdio.h>
 #include<string.h>
 #include<stdlib.h>
 #include<unistd.h>
 #include<math.h>
 #include<fcntl.h>
 #include<sys/types.h>
 #include<sys/stat.h>
 #include<sys/mman.h>
 #include<time.h>
 #include<dirent.h>
 #include<sys/errno.h>
 #include<sys/wait.h>
 #include<signal.h>
 #include<sys/param.h>
 #include<sys/syslog.h>
 #include<limits.h>
 #include<sys/time.h>
 #include<sys/ipc.h>
 #include<sys/msg.h>
 #include<sys/sem.h>
 #include<errno.h>
 #include<sys/shm.h>
 #include<pthread.h>
 #include<sys/syscall.h>
 #include<semaphore.h>
 #include<bits/pthreadtypes.h>
 #include<arpa/inet.h>
 #include<netinet/in.h>
 #include<sys/socket.h>
 #include<netdb.h>
 #define BUFLEN 255
 int main(int argc,char *argv[])
 {
 struct sockaddr_in peeraddr;
 struct in_addr ia;
 int sockft;
 char recmsg[BUFLEN+1];
 unsigned int socklen,n;
 struct hostent *group;
 struct ip_mreq mreq;
 if((sockft=socket(AF_INET,SOCK_DGRAM,0))<0)
 {
 printf(“socket creating err in udptalk\n”);
 exit(EXIT_FAILURE);
 }
 bzero(&mreq,sizeof(struct ip_mreq));
 if(argv[1])
 {
 if((group=gethostbyname(argv[1]))(struct hostent *)0)
 {
 perror(“gethostbyname”);
 exit(EXIT_FAILURE);
 }
 }
 else
 {
 printf(“you should give me a group address,24.0.0.0-239.255.255.255\n”);
 exit(EXIT_FAILURE);
 }
 bcopy((void *)group->h_addr,(void *)&ia,group->h_length);
 bcopy(&ia,&mreq.imr_multiaddr.s_addr,sizeof(struct in_addr));
 //mreq.imr_interface.s_addr=htonl(INADDR_ANY);
 //此句在某些平台将出现setsockopt设置失败,返回无此地址错误
 if(argv[2])
 {
 if(inet_pton(AF_INET,argv[2],&mreq.imr_interface.s_addr)<=0)
 {
 printf(“Wrong dest IP address!\n”);
 exit(EXIT_FAILURE);
 }
 }
 //设置客户端可接收组播消息,加入到组
 if(setsockopt(sockft,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(struct ip_mreq))-1)
 {
 perror(“setsockopt”);
 exit(EXIT_FAILURE);
 }
 socklen=sizeof(struct sockaddr_in);
 peeraddr.sin_family=AF_INET;
 peeraddr.sin_port=htons(7838);
 if(argv[2])
 { //
 if(inet_pton(AF_INET,argv[2],&peeraddr.sin_addr)<=0)
 {
 printf(“Wromg dest IP address!\n”);
 exit(EXIT_FAILURE);
 }
 }
 else
 {
 printf(“no group address given,224.0.0.0-39.255.255.255\n”);
 exit(EXIT_FAILURE);
 }
 if(bind(sockft,(struct sockaddr )&peeraddr,sizeof(struct sockaddr_in))==-1)
 {
 printf(“Bind error\n”);
 exit(EXIT_FAILURE);
 }
 for(;😉
 {
 bzero(recmsg,BUFLEN+1);
 n=recvfrom(sockft,recmsg,BUFLEN,0,(struct sockaddr)&peeraddr,&socklen); //接收组播消息
 if(n<0)
 {
 printf(“recvfrom err in udptalk!\n”);
 exit(EXIT_FAILURE);
 }
 else
 {
 recmsg[n]=0;
 printf(“peer:%s”,recmsg); //输出消息
 }
 }return 0;
 }

组播与广播很相似,不同的在于多了组播地址,在接受端中需要设置组播接口,使得接收端能够接收到组播信息

Android udp 组播demo udp组播代码_IP_02


接收端先运行,需要组号,当组号和发送端的目的组一致时可接受到数据。

Android udp 组播demo udp组播代码_Android udp 组播demo_03


执行发送端,发送hello i’m here,然后打印所发送的数据,再一次循环,等待新的输入。

Android udp 组播demo udp组播代码_Android udp 组播demo_04


接收端接收到信息,并再一次循环以阻塞的方式等下一个数据。这是在两个不同的主机中实现的组播通信。在发送端我们给定了组号的范围提示,但输入的组号不在该范围内会提醒,然后结束本次程序的运行,否则直接认为不是该组的成员。

在某一主机中执行接收端时有可能会因为没有网卡而出现setsockopt: No such device 错误,这时你需要添加显卡,route add -net 224.0.0.0 netmask 224.0.0.0 eth0 (or similar),eth0需要结合自己主机的IP地址来唯一的确认,如果不行可以使用sudo route add -net 224.0.0.0 netmask 224.0.0.0 eth0 (or similar)来解决。