linux 廣播


廣播是一台主機向局域網內的所有主機發送數據。這時,同一網段的所有主機都能接收到數據。發送廣播包的步驟大致如下:

(1)確定一個發送廣播的接口,如eth0

(2)確定廣播的地址,通過ioctl函數,請求碼設置為SIOCGIFBRDADDR得到廣播的地址

(3)使用這個廣播地址進行廣播

在局域網內,廣播通常用來探測服務器。

 

廣播發送端:

  1 主機:
  2 
  3 #include<stdio.h>
  4 #include<stdlib.h>
  5 #include<unistd.h>
  6 #include<string.h>
  7 #include<sys/socket.h>
  8 #include<arpa/inet.h>
  9 #include<netinet/in.h>
 10 #include<sys/types.h>
 11 #include<netdb.h>
 12 #include <sys/ioctl.h>
 13 #include <net/if.h>
 14 /**
 15 客戶端實現廣播
 16 
 17 
 18 **/
 19 #define IP_FOUND "IP_FOUND"
 20 #define IP_FOUND_ACK "IP_FOUND_ACK"
 21 #define IFNAME "eth0"
 22 #define MCAST_PORT 9999
 23 int main(int argc,char*argv[]){
 24 int ret=-1;
 25 
 26 
 27 struct sockaddr_in from_addr;//服務端地址
 28 int from_len=sizeof(from_addr);
 29 int count=-1;
 30 fd_set readfd;//讀文件描述符集合
 31 char buffer[1024];
 32 struct timeval timeout;
 33 timeout.tv_sec=2;//超時時間為2秒
 34 timeout.tv_usec=0;
 35 
 36 int sock=-1;
 37 sock=socket(AF_INET,SOCK_DGRAM,0);//建立數據報套接字
 38 if(sock<0){
 39   printf("HandleIPFound:sock init error\n");
 40   return;
 41 }
 42 
 43 
 44 //將使用的網絡接口名字復制到ifr.ifr_name中,由於不同的網卡接口的廣播地址是不一樣的,因此指定網卡接口
 45 
 46 struct ifreq ifr;
 47 strncpy(ifr.ifr_name,IFNAME,strlen(IFNAME));
 48 //發送命令,獲得網絡接口的廣播地址
 49 if(ioctl(sock,SIOCGIFBRDADDR,&ifr)==-1){
 50     perror("ioctl error");
 51     return;
 52 }
 53 
 54 //將獲得的廣播地址復制到broadcast_addr
 55 int so_broadcast=1;
 56 struct sockaddr_in broadcast_addr;//廣播地址
 57 memcpy(&broadcast_addr,&ifr.ifr_broadaddr,sizeof(struct sockaddr_in));
 58 
 59 
 60 //設置廣播端口號
 61 printf("broadcast IP is:%s\n",inet_ntoa(broadcast_addr.sin_addr));
 62 broadcast_addr.sin_family=AF_INET;
 63 broadcast_addr.sin_port=htons(MCAST_PORT);
 64 //默認的套接字描述符sock是不支持廣播,必須設置套接字描述符以支持廣播
 65 ret=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));
 66 
 67 
 68 
 69 //發送多次廣播,看網絡上是否有服務器存在
 70 int times=10;
 71 int i=0;
 72 for(i=0;i<times;i++){//一共發送10次廣播,每次等待2秒是否有回應
 73   //廣播發送服務器地址請求
 74     timeout.tv_sec=2;//超時時間為2秒
 75         timeout.tv_usec=0;
 76     ret=sendto(sock,IP_FOUND,strlen(IP_FOUND),0,(struct sockaddr*)&broadcast_addr,sizeof(broadcast_addr));
 77     if(ret==-1){
 78         continue;
 79     }
 80 
 81 //文件描述符清0
 82 FD_ZERO(&readfd);
 83 //將套接字文件描述符加入到文件描述符集合中
 84 FD_SET(sock,&readfd);
 85 //select偵聽是否有數據到來
 86 ret=select(sock+1,&readfd,NULL,NULL,&timeout);
 87 switch(ret){
 88  case -1:
 89     break;
 90  case 0:
 91     printf("timeout\n");
 92     break;
 93  default:
 94 //接收到數據
 95  if(FD_ISSET(sock,&readfd)){
 96     count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//from_addr為服務器端地址
 97     printf("recvmsg is %s\n",buffer);
 98     if(strstr(buffer,IP_FOUND_ACK)){
 99         printf("found server IP is:%s\n",inet_ntoa(from_addr.sin_addr));
100         //服務器端的發送端口號
101         printf("Server Port:%d\n",htons(from_addr.sin_port));
102     }
103   return;
104     
105 }
106  break;
107 
108 }
109 }
110 return;
111 }

廣播接收端:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <sys/types.h>
 4 #include <sys/socket.h>
 5 #include <fcntl.h>
 6 #include <linux/in.h>
 7 #include <stdlib.h>
 8 /**
 9 廣播接收端代碼
10 **/
11 #define IP_FOUND "IP_FOUND"
12 #define IP_FOUND_ACK "IP_FOUND_ACK"
13 #define PORT 9999
14 int main(int argc,char*argv[]){
15  int ret=-1;
16  int sock;
17  struct sockaddr_in server_addr;//服務器端地址
18  struct sockaddr_in from_addr;//客戶端地址
19  int from_len=sizeof(struct sockaddr_in);
20  int count=-1;
21  fd_set readfd;//讀文件描述符集合
22  char buffer[1024];
23  struct timeval timeout;
24  timeout.tv_sec=2;
25  timeout.tv_usec=0;
26  sock=socket(AF_INET,SOCK_DGRAM,0);//建立數據報套接字
27  if(sock<0){
28     perror("sock error");
29     return;
30 }
31 
32 memset((void*)&server_addr,0,sizeof(struct sockaddr_in));
33 server_addr.sin_family=AF_INET;
34 server_addr.sin_addr.s_addr=htons(INADDR_ANY);
35 server_addr.sin_port=htons(PORT);
36 //將地址結構綁定到套接字上./
37 ret=bind(sock,(struct sockaddr*)&server_addr,sizeof(server_addr));
38 if(ret<0){
39     perror("bind error");
40     return;
41 }
42 
43 while(1){
44 timeout.tv_sec=2;
45 timeout.tv_usec=0;
46 //文件描述符集合清0
47 FD_ZERO(&readfd);
48 //將套接字描述符加入到文件描述符集合
49 FD_SET(sock,&readfd);
50 //select偵聽是否有數據到來
51 ret=select(sock+1,&readfd,NULL,NULL,&timeout);//偵聽是否可讀
52 printf("ret=%d\n",ret);
53 switch(ret){
54 case -1://發生錯誤
55 break;
56 case 0://超時
57 printf("timeout\n");
58 break;
59 default:
60 if(FD_ISSET(sock,&readfd)){
61     count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//接收客戶端發送的數據
62     //from_addr保存客戶端的地址結構
63     if(strstr(buffer,IP_FOUND)){
64         //響應客戶端請求
65         //打印客戶端的IP地址
66             printf("Client IP is%s\n",inet_ntoa(from_addr.sin_addr));
67         //打印客戶端的端口號
68         printf("Client Send Port:%d\n",ntohs(from_addr.sin_port));
69         memcpy(buffer,IP_FOUND_ACK,strlen(IP_FOUND_ACK)+1);
70         count=sendto(sock,buffer,strlen(buffer),0,(struct sockaddr*)&from_addr,from_len);//將數據發送給客戶端
71     }
72  return;
73 }
74 break;
75 }
76 }
77 return;
78 }

轉自:

http://blog.csdn.net/chenjin_zhong/article/details/7270213


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM