Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2707671
  • 博文数量: 505
  • 博客积分: 1552
  • 博客等级: 上尉
  • 技术积分: 2514
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-23 18:24
文章分类

全部博文(505)

文章存档

2019年(12)

2018年(15)

2017年(1)

2016年(17)

2015年(14)

2014年(93)

2013年(233)

2012年(108)

2011年(1)

2009年(11)

分类: LINUX

2016-08-08 10:59:53

广播是一台主机向局域网内的所有主机发送数据。这时,同一网段的所有主机都能接收到数据。发送广播包的步骤大致如下:

(1)确定一个发送广播的接口,如eth0

(2)确定广播的地址,通过ioctl函数,请求码设置为SIOCGIFBRDADDR得到广播的地址

(3)使用这个广播地址进行广播

在局域网内,广播通常用来探测服务器。

 

广播发送端:


点击(此处)折叠或打开

  1. 主机:

  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<unistd.h>
  5. #include<string.h>
  6. #include<sys/socket.h>
  7. #include<arpa/inet.h>
  8. #include<netinet/in.h>
  9. #include<sys/types.h>
  10. #include<netdb.h>
  11. #include <sys/ioctl.h>
  12. #include <net/if.h>
  13. /**
  14. 客户端实现广播


  15. **/
  16. #define IP_FOUND "IP_FOUND"
  17. #define IP_FOUND_ACK "IP_FOUND_ACK"
  18. #define IFNAME "eth0"
  19. #define MCAST_PORT 9999
  20. int main(int argc,char*argv[]){
  21. int ret=-1;


  22. struct sockaddr_in from_addr;//服务端地址
  23. int from_len=sizeof(from_addr);
  24. int count=-1;
  25. fd_set readfd;//读文件描述符集合
  26. char buffer[1024];
  27. struct timeval timeout;
  28. timeout.tv_sec=2;//超时时间为2秒
  29. timeout.tv_usec=0;

  30. int sock=-1;
  31. sock=socket(AF_INET,SOCK_DGRAM,0);//建立数据报套接字
  32. if(sock<0){
  33.   printf("HandleIPFound:sock init error\n");
  34.   return;
  35. }


  36. //将使用的网络接口名字复制到ifr.ifr_name中,由于不同的网卡接口的广播地址是不一样的,因此指定网卡接口

  37. struct ifreq ifr;
  38. strncpy(ifr.ifr_name,IFNAME,strlen(IFNAME));
  39. //发送命令,获得网络接口的广播地址
  40. if(ioctl(sock,SIOCGIFBRDADDR,&ifr)==-1){
  41.     perror("ioctl error");
  42.     return;
  43. }

  44. //将获得的广播地址复制到broadcast_addr
  45. int so_broadcast=1;
  46. struct sockaddr_in broadcast_addr;//广播地址
  47. memcpy(&broadcast_addr,&ifr.ifr_broadaddr,sizeof(struct sockaddr_in));


  48. //设置广播端口号
  49. printf("broadcast IP is:%s\n",inet_ntoa(broadcast_addr.sin_addr));
  50. broadcast_addr.sin_family=AF_INET;
  51. broadcast_addr.sin_port=htons(MCAST_PORT);
  52. //默认的套接字描述符sock是不支持广播,必须设置套接字描述符以支持广播
  53. ret=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));



  54. //发送多次广播,看网络上是否有服务器存在
  55. int times=10;
  56. int i=0;
  57. for(i=0;i<times;i++){//一共发送10次广播,每次等待2秒是否有回应
  58.   //广播发送服务器地址请求
  59.     timeout.tv_sec=2;//超时时间为2秒
  60.         timeout.tv_usec=0;
  61.     ret=sendto(sock,IP_FOUND,strlen(IP_FOUND),0,(struct sockaddr*)&broadcast_addr,sizeof(broadcast_addr));
  62.     if(ret==-1){
  63.         continue;
  64.     }

  65. //文件描述符清0
  66. FD_ZERO(&readfd);
  67. //将套接字文件描述符加入到文件描述符集合中
  68. FD_SET(sock,&readfd);
  69. //select侦听是否有数据到来
  70. ret=select(sock+1,&readfd,NULL,NULL,&timeout);
  71. switch(ret){
  72.  case -1:
  73.     break;
  74.  case 0:
  75.     printf("timeout\n");
  76.     break;
  77.  default:
  78. //接收到数据
  79.  if(FD_ISSET(sock,&readfd)){
  80.     count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//from_addr为服务器端地址
  81.     printf("recvmsg is %s\n",buffer);
  82.     if(strstr(buffer,IP_FOUND_ACK)){
  83.         printf("found server IP is:%s\n",inet_ntoa(from_addr.sin_addr));
  84.         //服务器端的发送端口号
  85.         printf("Server Port:%d\n",htons(from_addr.sin_port));
  86.     }
  87.   return;
  88.     
  89. }
  90.  break;

  91. }
  92. }
  93. return;
  94. }



广播接收端:

点击(此处)折叠或打开

  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. memset((void*)&server_addr,0,sizeof(struct sockaddr_in));
  32. server_addr.sin_family=AF_INET;
  33. server_addr.sin_addr.s_addr=htons(INADDR_ANY);
  34. server_addr.sin_port=htons(PORT);
  35. //将地址结构绑定到套接字上./
  36. ret=bind(sock,(struct sockaddr*)&server_addr,sizeof(server_addr));
  37. if(ret<0){
  38.     perror("bind error");
  39.     return;
  40. }

  41. while(1){
  42. timeout.tv_sec=2;
  43. timeout.tv_usec=0;
  44. //文件描述符集合清0
  45. FD_ZERO(&readfd);
  46. //将套接字描述符加入到文件描述符集合
  47. FD_SET(sock,&readfd);
  48. //select侦听是否有数据到来
  49. ret=select(sock+1,&readfd,NULL,NULL,&timeout);//侦听是否可读
  50. printf("ret=%d\n",ret);
  51. switch(ret){
  52. case -1://发生错误
  53. break;
  54. case 0://超时
  55. printf("timeout\n");
  56. break;
  57. default:
  58. if(FD_ISSET(sock,&readfd)){
  59.     count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//接收客户端发送的数据
  60.     //from_addr保存客户端的地址结构
  61.     if(strstr(buffer,IP_FOUND)){
  62.         //响应客户端请求
  63.         //打印客户端的IP地址
  64.             printf("Client IP is%s\n",inet_ntoa(from_addr.sin_addr));
  65.         //打印客户端的端口号
  66.         printf("Client Send Port:%d\n",ntohs(from_addr.sin_port));
  67.         memcpy(buffer,IP_FOUND_ACK,strlen(IP_FOUND_ACK)+1);
  68.         count=sendto(sock,buffer,strlen(buffer),0,(struct sockaddr*)&from_addr,from_len);//将数据发送给客户端
  69.     }
  70.  return;
  71. }
  72. break;
  73. }
  74. }
  75. return;
  76. }


阅读(1430) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~