广播和多播编程都是建立在UDP通信的基础上,通过setsockopt函数即可发送广播数据报或多播数据报。
int setsockopt(int fd,int level,int optname,const char*optval,int optlen)
参数:1、套接字描述符
2、选项定义层次,可为SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP。在广播中使用SOL_SOCKET
3、根据第二个参数,可为不同的值,在选定SOL_SOCKET的前提下,可为
SO_BROADCAST:允许发送广播数据报
SO_RCVBUF:接受缓冲区大小
SO_SNDBUF:发送缓冲区大小
4、第三个参数的长度
用于设置状态字的选项值设置。成功返回0,失败返回-1
广播:
接受方
1 #include<iostream> 2 #include<arpa/inet.h> 3 #include<stdio.h> 4 #include<string.h> 5 #include<sys/socket.h> 6 #include<sys/types.h> 7 #include<netinet/in.h> 8 #include<unistd.h> 9 using namespace std; 10 11 int main() 12 { 13 struct sockaddr_in addr,recvaddr; 14 socklen_t len=sizeof(recvaddr); 15 int sockfd,op; 16 char buf[512]; 17 18 sockfd=socket(AF_INET,SOCK_DGRAM,0); 19 if(sockfd<0) 20 { 21 cout<<"socket error"<<endl; 22 return -1; 23 } 24 25 addr.sin_family=AF_INET; 26 addr.sin_port=htons(2501); 27 addr.sin_addr.s_addr=htons(INADDR_ANY); 28 29 op=bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)); 30 if(op<0) 31 { 32 cout<<"bind error"<<endl; 33 return -1; 34 } 35 36 recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&recvaddr,&len); 37 cout<<"recv data from "<<ntohs(recvaddr.sin_port)<<" :"<<buf<<endl; 38 39 //char buff[512]="1234567890987654321"; 40 //sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&recvaddr,len); 41 return 0; 42 }
发送广播数据:
1 #include<sys/socket.h> 2 #include<sys/types.h> 3 #include<iostream> 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<string.h> 7 #include<netinet/in.h> 8 #include<arpa/inet.h> 9 using namespace std; 10 11 int main() 12 { 13 int sockfd; 14 int op; 15 struct sockaddr_in addr,saddr; 16 socklen_t len=sizeof(saddr); 17 int i,j; 18 19 sockfd=socket(AF_INET,SOCK_DGRAM,0); 20 if(sockfd<0) 21 { 22 cout<<"socket error"<<endl; 23 return -1; 24 } 25 26 addr.sin_family=AF_INET; 27 addr.sin_port=htons(2501); 28 addr.sin_addr.s_addr=htons(INADDR_ANY); 29 30 int yes=1; 31 setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&yes,sizeof(yes)); 32 char buff[512]="0987654321234567890"; 33 sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&addr,sizeof(addr)); 34 cout<<"send: "<<buff<<endl; 35 36 return 0; 37 }
多播:
广播会向同一子网的主机发送消息,有时候会严重浪费网络带宽;而多播则只会向出于同一多播组的主机发送消息。
这里先说一下IPv4多播地址结构体:
struct in_addr
{
in_addr_t s_addr;
}
sturct ip_mreq
{
struct in_addr imr_multiaddr;//多播组IP,类似QQ中的QQ群号,范围224.0.0.0到239.255.255.255其中224.0.0.0不可取
struct in_addr imr_interface;//要加入多播组的IP
}
int setsockopt(int fd,int level,int optname,const char*optval,int optlen)
参数:1、套接字描述符
2、选项定义层次,可为SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP。在多播中使用IPPROTO_IP
3、根据第二个参数,可为不同的值,在选定IPPROTO_IP的前提下,可为
IP_ADD_MEMBERSHIP:加入多播组
IP_DROP_MEMBERSHIP:离开多播组
IP_MULTICAST_LOOP:设置回环许可,即自己发送的多播数据会发送到本地回环接口
4、第三个参数的长度
用于设置状态字的选项值设置。成功返回0,失败返回-1
广播:
接受方
1 #include<sys/socket.h> 2 #include<sys/types.h> 3 #include<iostream> 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<string.h> 7 #include<netinet/in.h> 8 #include<arpa/inet.h> 9 #include<errno.h> 10 #include<unistd.h> 11 using namespace std; 12 13 int main(int argc,char**argv) 14 { 15 int sockfd; 16 int op; 17 struct sockaddr_in addr,saddr; 18 socklen_t len=sizeof(saddr); 19 int i,j; 20 21 sockfd=socket(AF_INET,SOCK_DGRAM,0); 22 if(sockfd<0) 23 { 24 cout<<"socket error"<<endl; 25 return -1; 26 } 27 28 memset(&addr,0,sizeof(addr)); 29 addr.sin_family=AF_INET; 30 addr.sin_port=htons(8000);//多播服务器端口,使用别的端口会返回errno=22 31 addr.sin_addr.s_addr=htonl(INADDR_ANY); 32 op=bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)); 33 if(op<0) 34 { 35 cout<<"bind error"<<endl; 36 return 0; 37 } 38 39 int yes=1; 40 op=setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_LOOP,&yes,sizeof(yes));//设置回环许可 41 if(op<0) 42 { 43 cout<<"set LOOP error"<<endl; 44 return 0; 45 } 46 struct ip_mreq mreq; 47 bzero(&mreq,sizeof(mreq)); 48 mreq.imr_multiaddr.s_addr=inet_addr("224.0.0.88"); 49 mreq.imr_interface.s_addr=htonl(INADDR_ANY); 50 51 op=setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mreq,sizeof(mreq)); 52 if(op<0) 53 { 54 cout<<errno<<endl; 55 return 0; 56 } 57 58 char buff[512]; 59 char recv_buff[512]=""; 60 cout<<"111"<<endl; 61 for(i=1;i<=5;i++) 62 { 63 sleep(3); 64 memset(recv_buff,0,sizeof(recv_buff)); 65 len=sizeof(addr); 66 recvfrom(sockfd,recv_buff,sizeof(recv_buff),0,(struct sockaddr*)&addr,&len); 67 cout<<"recv: "<<recv_buff<<endl; 68 } 69 70 return 0; 71 }
发送方:
1 #include<sys/socket.h> 2 #include<sys/types.h> 3 #include<iostream> 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<string.h> 7 #include<netinet/in.h> 8 #include<arpa/inet.h> 9 #include<errno.h> 10 #include<unistd.h> 11 using namespace std; 12 int main() 13 { 14 struct sockaddr_in addr; 15 socklen_t len; 16 int i,j; 17 int sockfd=socket(AF_INET,SOCK_DGRAM,0); 18 addr.sin_family=AF_INET; 19 addr.sin_port=htons(8000);//多播服务器端口 20 addr.sin_addr.s_addr=inet_addr("224.0.0.88"); 21 22 char buff[512]="123456789"; 23 for(i=9;i<=14;i++) 24 { 25 sleep(3); 26 buff[i]=(i-8)+'0'; 27 buff[i+1]=0; 28 len=sizeof(addr); 29 sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&addr,sizeof(addr)); 30 cout<<"1111"<<endl; 31 32 } 33 return 0; 34 35 }
参考书籍——《Linux网络编程》