广播是一台主机向局域网内的所有主机发送数据。这时,同一网段的所有主机都能接收到数据。发送广播包的步骤大致如下:
(1)确定一个发送广播的接口,如eth0
(2)确定广播的地址,通过ioctl函数,请求码设置为SIOCGIFBRDADDR得到广播的地址
(3)使用这个广播地址进行广播
在局域网内,广播通常用来探测服务器。
广播发送端:
-
主机:
-
-
#include<stdio.h>
-
#include<stdlib.h>
-
#include<unistd.h>
-
#include<string.h>
-
#include<sys/socket.h>
-
#include<arpa/inet.h>
-
#include<netinet/in.h>
-
#include<sys/types.h>
-
#include<netdb.h>
-
#include <sys/ioctl.h>
-
#include <net/if.h>
-
/**
-
客户端实现广播
-
-
-
**/
-
#define IP_FOUND "IP_FOUND"
-
#define IP_FOUND_ACK "IP_FOUND_ACK"
-
#define IFNAME "eth0"
-
#define MCAST_PORT 9999
-
int main(int argc,char*argv[]){
-
int ret=-1;
-
-
-
struct sockaddr_in from_addr;//服务端地址
-
int from_len=sizeof(from_addr);
-
int count=-1;
-
fd_set readfd;//读文件描述符集合
-
char buffer[1024];
-
struct timeval timeout;
-
timeout.tv_sec=2;//超时时间为2秒
-
timeout.tv_usec=0;
-
-
int sock=-1;
-
sock=socket(AF_INET,SOCK_DGRAM,0);//建立数据报套接字
-
if(sock<0){
-
printf("HandleIPFound:sock init error\n");
-
return;
-
}
-
-
-
//将使用的网络接口名字复制到ifr.ifr_name中,由于不同的网卡接口的广播地址是不一样的,因此指定网卡接口
-
-
struct ifreq ifr;
-
strncpy(ifr.ifr_name,IFNAME,strlen(IFNAME));
-
//发送命令,获得网络接口的广播地址
-
if(ioctl(sock,SIOCGIFBRDADDR,&ifr)==-1){
-
perror("ioctl error");
-
return;
-
}
-
-
//将获得的广播地址复制到broadcast_addr
-
int so_broadcast=1;
-
struct sockaddr_in broadcast_addr;//广播地址
-
memcpy(&broadcast_addr,&ifr.ifr_broadaddr,sizeof(struct sockaddr_in));
-
-
-
//设置广播端口号
-
printf("broadcast IP is:%s\n",inet_ntoa(broadcast_addr.sin_addr));
-
broadcast_addr.sin_family=AF_INET;
-
broadcast_addr.sin_port=htons(MCAST_PORT);
-
//默认的套接字描述符sock是不支持广播,必须设置套接字描述符以支持广播
-
ret=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));
-
-
-
-
//发送多次广播,看网络上是否有服务器存在
-
int times=10;
-
int i=0;
-
for(i=0;i<times;i++){//一共发送10次广播,每次等待2秒是否有回应
-
//广播发送服务器地址请求
-
timeout.tv_sec=2;//超时时间为2秒
-
timeout.tv_usec=0;
-
ret=sendto(sock,IP_FOUND,strlen(IP_FOUND),0,(struct sockaddr*)&broadcast_addr,sizeof(broadcast_addr));
-
if(ret==-1){
-
continue;
-
}
-
-
//文件描述符清0
-
FD_ZERO(&readfd);
-
//将套接字文件描述符加入到文件描述符集合中
-
FD_SET(sock,&readfd);
-
//select侦听是否有数据到来
-
ret=select(sock+1,&readfd,NULL,NULL,&timeout);
-
switch(ret){
-
case -1:
-
break;
-
case 0:
-
printf("timeout\n");
-
break;
-
default:
-
//接收到数据
-
if(FD_ISSET(sock,&readfd)){
-
count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//from_addr为服务器端地址
-
printf("recvmsg is %s\n",buffer);
-
if(strstr(buffer,IP_FOUND_ACK)){
-
printf("found server IP is:%s\n",inet_ntoa(from_addr.sin_addr));
-
//服务器端的发送端口号
-
printf("Server Port:%d\n",htons(from_addr.sin_port));
-
}
-
return;
-
-
}
-
break;
-
-
}
-
}
-
return;
-
}
广播接收端:
-
#include <stdio.h>
-
#include <string.h>
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <fcntl.h>
-
#include <linux/in.h>
-
#include <stdlib.h>
-
/**
-
广播接收端代码
-
**/
-
#define IP_FOUND "IP_FOUND"
-
#define IP_FOUND_ACK "IP_FOUND_ACK"
-
#define PORT 9999
-
int main(int argc,char*argv[]){
-
int ret=-1;
-
int sock;
-
struct sockaddr_in server_addr;//服务器端地址
-
struct sockaddr_in from_addr;//客户端地址
-
int from_len=sizeof(struct sockaddr_in);
-
int count=-1;
-
fd_set readfd;//读文件描述符集合
-
char buffer[1024];
-
struct timeval timeout;
-
timeout.tv_sec=2;
-
timeout.tv_usec=0;
-
sock=socket(AF_INET,SOCK_DGRAM,0);//建立数据报套接字
-
if(sock<0){
-
perror("sock error");
-
return;
-
}
-
-
memset((void*)&server_addr,0,sizeof(struct sockaddr_in));
-
server_addr.sin_family=AF_INET;
-
server_addr.sin_addr.s_addr=htons(INADDR_ANY);
-
server_addr.sin_port=htons(PORT);
-
//将地址结构绑定到套接字上./
-
ret=bind(sock,(struct sockaddr*)&server_addr,sizeof(server_addr));
-
if(ret<0){
-
perror("bind error");
-
return;
-
}
-
-
while(1){
-
timeout.tv_sec=2;
-
timeout.tv_usec=0;
-
//文件描述符集合清0
-
FD_ZERO(&readfd);
-
//将套接字描述符加入到文件描述符集合
-
FD_SET(sock,&readfd);
-
//select侦听是否有数据到来
-
ret=select(sock+1,&readfd,NULL,NULL,&timeout);//侦听是否可读
-
printf("ret=%d\n",ret);
-
switch(ret){
-
case -1://发生错误
-
break;
-
case 0://超时
-
printf("timeout\n");
-
break;
-
default:
-
if(FD_ISSET(sock,&readfd)){
-
count=recvfrom(sock,buffer,1024,0,(struct sockaddr*)&from_addr,&from_len);//接收客户端发送的数据
-
//from_addr保存客户端的地址结构
-
if(strstr(buffer,IP_FOUND)){
-
//响应客户端请求
-
//打印客户端的IP地址
-
printf("Client IP is%s\n",inet_ntoa(from_addr.sin_addr));
-
//打印客户端的端口号
-
printf("Client Send Port:%d\n",ntohs(from_addr.sin_port));
-
memcpy(buffer,IP_FOUND_ACK,strlen(IP_FOUND_ACK)+1);
-
count=sendto(sock,buffer,strlen(buffer),0,(struct sockaddr*)&from_addr,from_len);//将数据发送给客户端
-
}
-
return;
-
}
-
break;
-
}
-
}
-
return;
-
}
阅读(1476) | 评论(0) | 转发(0) |