• 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
    ");
     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
    ",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
    ");
     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
    ",buffer);
     98     if(strstr(buffer,IP_FOUND_ACK)){
     99         printf("found server IP is:%s
    ",inet_ntoa(from_addr.sin_addr));
    100         //服务器端的发送端口号
    101         printf("Server Port:%d
    ",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
    ",ret);
    53 switch(ret){
    54 case -1://发生错误
    55 break;
    56 case 0://超时
    57 printf("timeout
    ");
    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
    ",inet_ntoa(from_addr.sin_addr));
    67         //打印客户端的端口号
    68         printf("Client Send Port:%d
    ",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

  • 相关阅读:
    记录python爬取猫眼票房排行榜(带stonefont字体网页),保存到text文件,csv文件和MongoDB数据库中
    分析Ajax来爬取今日头条街拍美图并保存到MongDB
    把SQLAlchemy查询对象转换成字典/json使用(汇总)
    把SQLAlchemy查询对象转换成字典/json使用(分开)
    使用Flask_SQLAlchemy连接多个数据库
    SQLAlchemy小知识点
    flask_sqlalchemy和sqlalchemy联系区别及其使用方式
    使用Requests+正则表达式爬取猫眼TOP100电影并保存到文件或MongoDB,并下载图片
    使用python脚本定时备份web网站
    使用shell脚本定时备份web网站代码
  • 原文地址:https://www.cnblogs.com/meizixiong/p/3228182.html
Copyright © 2020-2023  润新知