多播是一种点对多点的通信方式,互联网中的D类地址用于组播: 224.0.0.0-239.255.255.255
多播地址分类
- 局部多播地址224.0.0.0-224.0.0.255 为路由协议和其它用途的保留地址
- 预留多播地址224.0.1.0-238.255.255.255 可用于全球范围
- 管理权限多播地址为 239.0.0.0~239.255.255.255,可供组织内部使用,类似于私有 IP 地址,不能用于 Internet,可限制多播范围。
A类地址(其中网络号为0,10,127位特殊地址)
| 第一字节 | 第二字节 | 第三字节 | 第四字节 |
| 0 | 网络号 | 主机号 |
B类地址
| 第一字节 | 第二字节 | 第三字节 | 第四字节 |
| 0 | 1| 网络号 | 主机号 |
C类地址
| 第一字节 | 第二字节 | 第三字节 | 第四字节 |
|0|1|0| 网络号 | 主机号 |
组播基于无连接的udp协议实现数据发送和接收
创建socket
int socket(int domain, int type, int protocol);
domain设置成AF_INET,一般使用基于IP协议的UDP,TCP通信创建套接字都使用这个选项
type设置成 SOCK_DGRAM 用户数据包协议
绑定本地IP地址到套接字
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
const struct sockaddr *addr: 设置好的本机所有IP地址
设置组播属性,加入到组播:
setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
level:IPPROTO_IP
int optname:IP_ADD_MEMBERSHIP //加入多播组
optval:设置好的多播结构体(多播IP:226.1.1.1)
接收数据
recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
int sockfd :句柄
struct sockaddr *src_addr 绑定的地址
使用多播技术加入
#include <stdio.h>
#include <netinet/in.h> //for souockaddr_in
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
//for select
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
#include <strings.h> //for bzero
#include <string.h>
char msg[1000];
int main(int argc,char **argv)
{
int sockfd,nlen,ret,on=-1;
int loop = 1;
struct sockaddr_in serveraddr;
struct ip_mreq group;//多播结构体
sockfd=socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0)
{
printf("sock err\n");
return -1;
}
//setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,&on, sizeof(on));
serveraddr.sin_family= AF_INET; //IPV4
serveraddr.sin_port = htons(8888);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
nlen=sizeof(serveraddr);
ret=bind(sockfd, (struct sockaddr *)&serveraddr,nlen);
if(ret<0)
{
printf("bind err\n");
return -1;
}
ret = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP,
&loop, sizeof(loop));
if (ret < 0)
{
printf("setsockopt\n");
return -1;
}
//设置多播结构体
//设置多播组IP
group.imr_multiaddr.s_addr = inet_addr("226.1.1.1");
//将本机加入多播组
group.imr_interface.s_addr = INADDR_ANY;
ret=setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&group,sizeof(group));
if(ret<0)
{
printf("Adding multicast group error\n");
close(sockfd);
return -1;
}
else printf("Adding multicast group...OK.\n");
while(1)
{
memset(msg,0,1000);
ret = recvfrom(sockfd, msg, sizeof(msg), 0,(struct sockaddr*)&serveraddr, &nlen);
if( ret== -1)
{
perror("recvfrom()");
}
printf("msg:\n%s",msg);
sleep(1);
}
}
向创建好的"226.1.1.1"多播组发送消息:
#include <stdio.h>
#include <netinet/in.h> //for souockaddr_in
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
//for select
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
#include <strings.h> //for bzero
#include <string.h>
char msg[1000];
int main(int argc,char **argv)
{
int sockfd,nlen,ret,on=1;
struct sockaddr_in local_addr;
struct ip_mreq group;
//socklen_t length;
sockfd=socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0)
{
printf("sock err\n");
return -1;
}
// setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,&on, sizeof(on));
local_addr.sin_family= AF_INET; //IPV4
local_addr.sin_port = htons(8888);
local_addr.sin_addr.s_addr = inet_addr("226.1.1.1"); //
nlen=sizeof(local_addr);
while(1)
{
if(fgets(msg,999,stdin))
{
ret=sendto(sockfd, msg, strlen(msg), 0,(struct sockaddr*)&local_addr, sizeof(local_addr));
if(ret<0)
{
printf("send err");
return -1;
}
}
}
}