Linux網路程式設計——廣播、多播
廣播和多播程式設計都是建立在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 namespacestd; 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網路程式設計》