使用SOCK_DGRAM在Linux上发送全网广播包:
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>
#define PORT 7773
#define MAXDATASIZE 256
int main(int argc,char *argv[])
{
int ret,socket_fd;
struct sockaddr_in my_addr;
char buf[MAXDATASIZE];
int so_broadcast=1;
socklen_t size;
char my_ip[12];
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(PORT);
my_addr.sin_addr.s_addr=inet_addr("255.255.255.255");
bzero(&(my_addr.sin_zero),8);
if((socket_fd=(socket(AF_INET,SOCK_DGRAM,0)))==-1) {
perror("socket");
exit(1);
}
setsockopt(socket_fd,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));
strcpy(buf,"Hello,I'm on line!");
while(1) {
ret=sendto(socket_fd,buf,strlen(buf),0,(struct sockaddr *)&my_addr,sizeof(my_addr));
sleep(1);
printf("next:%d\n",ret);
}
return 0;
}
还必须运行此命令,不然即使sendto不报错,实质上也发不出去,对方抓包都抓不到。有些系统会提示:No Route to host.
route add -host 255.255.255.255 dev eth0
由于系统差异,有些系统的UDP协议不支持发送全网广播包,只能发送子网广播包,因此只能使用SOCK_RAW构建UDP包,这样就能实现全网广播包:
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>
#define UDP_HEADER_SIZE 8
#define IP_HEADER_SIZE 20
typedef struct udp_hdr{
unsigned short s_port;
unsigned short d_port;
unsigned short length;
unsigned short cksum;
char data[0];
}udp_hdr;
int
send_bcast(char *send_data,char *src_ip, uint16_t src_port, uint16_t dest_port)
{
int sd;
udp_hdr *udp;
int count = -1; /* # of expected bcasts,
* default infinite */
int send_cnt = 0; /* # of bcasts sent */
int recv_cnt = 0; /* # of bcasts received on
* current send */
int udplen; /* Total length of packets sent */
struct sockaddr_in laddr; /* Local address */
socklen_t laddr_len; /* Local address */
struct sockaddr_in faddr; /* Foreign address */
int datalen = strlen(send_data); /* data length. */
/* Parameters (command line options) */
char *host;
unsigned int ipaddr;
char *data;
unsigned char ttl = 64; /* IP_MULTICAST_TTL default 1, must change to 64 */
/* Set 'ipaddr' from first non-option argument. */
host = "255.255.255.255";
ipaddr = inet_addr("255.255.255.255");
if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
{
perror("socket");
goto fail;
}
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL,(char *)&ttl, sizeof(unsigned char)) == -1)
{
perror("setsockopt(IP_MULTICAST_TTL)");
}
int on=1;
setsockopt(sd,SOL_SOCKET,SO_REUSEADDR | SO_BROADCAST,&on,sizeof(on));
/* Our local address */
memset(&laddr, 0, sizeof(laddr));
laddr.sin_family = AF_INET;
laddr.sin_addr.s_addr = inet_addr(src_ip);
/* Foreign adddress (for connect/sendto) */
memset(&faddr, 0, sizeof(faddr));
faddr.sin_family = AF_INET;
faddr.sin_addr.s_addr = ipaddr;
/*
* Initialize the send buffer with an request.
*/
udplen = datalen + UDP_HEADER_SIZE;
udp = malloc(udplen);
data = udp->data;
memcpy(data,send_data,datalen);
udp->s_port = htons(src_port);
udp->d_port = htons(dest_port);
udp->length = udplen;
udp->cksum = 0;
//udp->cksum = chksum((U16 *)udp, udplen);
laddr_len = sizeof(laddr);
getsockname(sd, (struct sockaddr *)&laddr, &laddr_len);
printf("bcast %s (%s) ", host, inet_ntoa(*((struct in_addr *)&ipaddr)));
if (laddr.sin_addr.s_addr != 0)
{
printf("from %s: ", inet_ntoa(laddr.sin_addr));
}
printf("%d(%d) bytes of data.\n", datalen, udplen+IP_HEADER_SIZE);
/*
* Send one echo request
*/
int retval = sendto(sd, udp, udplen, 0,
(struct sockaddr *)&faddr, sizeof(faddr));
if (retval == -1)
{
perror("sendto");
}
fail:
/* Cleanup and exit. */
if (udp) free(udp);
if (sd != -1) close(sd);
usage:
return 0;
}
int main(int argc, char *argv[])
{
int c;
int enable_double=0;
int cycles=0;
char *data;
while ((c = getopt(argc, argv, "r:d:")) != -1)
{
switch (c)
{
case 'r':
cycles = (uint32_t)strtol(optarg,NULL,10);
break;
case 'd':
data = optarg;
break;
}
}
if(cycles)
{
if(data==NULL)
{
data="hello";
}
while(cycles--)
{
send_bcast(data,"10.69.2.214",13334,8080);
}
}
return 0;
}