1. 程式人生 > 實用技巧 >Linux網路程式設計——廣播、多播

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 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網路程式設計》