广播UDP与单播UDP的区别就是IP地址不同,广播使用广播地址255.255.255.255,将消息发送到在同一广播网络上的每个主机。值得强调的是:本地广播信息是不会被路由器转发。当然这是十分容易理解的,因为如果路由器转发了广播信息,那么势必会引起网络瘫痪。这也是为什么IP协议的设计者故意没有定义互联网范围的广播机制。
广播地址通常用于在网络游戏中处于同一本地网络的玩家之间交流状态信息等。
其实广播顾名思义,就是想局域网内所有的人说话,但是广播还是要指明接收者的端口号的,因为不可能接受者的所有端口都来收听广播。
注意:如果没有设置BLOADCASE选项的不递送。如果bind端口不匹配不递送该套接口如果绑定的不是INADDR_ANY话,那么BIND的地址和目的地址匹配才能递送:也就是说你必须BIND一个广播地址或者绑定INADDR_ANY
-
用ifconfig命令可以disable块网卡的BROADCAST标志,让其不能接受以太网广播。
-
也可以使用ioctl的SIOCSIFFLAGS方法去掉一个接口的标志IFF_BROADCAST,使之不能接受以太网广播。
UDP广播demo
udp_brodcast_send.c (发送方)
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
struct sockaddr_in s_addr;
int sock;
int addr_len;
int len;
char buff[128];
int yes;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket");
exit(EXIT_FAILURE);
} else
printf("create socket.\n\r");
yes = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(7838);
if (argv[1])
s_addr.sin_addr.s_addr = inet_addr(argv[1]);
else {
printf("input sever ip!\n");
exit(0);
}
addr_len = sizeof(s_addr);
strcpy(buff, "hello message");
len = sendto(sock, buff, strlen(buff), 0,
(struct sockaddr *) &s_addr, addr_len);
if (len < 0) {
printf("\n\rsend error.\n\r");
exit(EXIT_FAILURE);
}
printf("send success.\n\r");
return 0;
}
udp_bordcast_rcv.c (接收方)
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
int sock;
socklen_t addr_len;
int len;
char buff[128];
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket");
exit(EXIT_FAILURE);
} else
printf("create socket.\n\r");
memset(&s_addr, 0, sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(7838);
s_addr.sin_addr.s_addr = INADDR_ANY;
if ((bind(sock, (struct sockaddr *) &s_addr, sizeof(s_addr))) == -1)
{
perror("bind");
exit(EXIT_FAILURE);
} else
printf("bind address to socket.\n\r");
addr_len = sizeof(c_addr);
while (1)
{
len = recvfrom(sock, buff, sizeof(buff) - 1, 0,
(struct sockaddr *) &c_addr, &addr_len);
if (len < 0)
{
perror("recvfrom");
exit(EXIT_FAILURE);
}
buff[len] = '\0';
printf("recive come from %s:%d message:%s\n\r",
inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port), buff);
}
return 0;
}
编译
- gcc udp_bordcast_rcv.c -o udp_bordcast_rcv
- gcc udp_bordcast_send.c -o udp_bordcast_send
运行
./udp_bordcast_rcv 192.168.xxxx
./udp_bordcast_send 127.0.0.1