加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Linux Socket详解 <七> UDP广播

(2015-03-11 11:02:04)
标签:

linux

socket

broadcast

udp

分类: linux
作者: Sam (甄峰)  sam_code@hotmail.com

之前谈到UDP可以发送广播,这里就讨论下UDP广播。

0. 广播的应用:
在某个子网内,有一台特定设备,但我们不清楚这台设备的地址,可以通过发送UDP广播,设备接收到此特定广播后回复。则可以得到设备的地址。
频繁的广播会加大网络负载,因为它会发送数据到每个地址。


1. 广播地址:
IP地址由两部分组成,NetID(网络地址)和HostID(主机地址)。
网络掩码用于把网络地址从IP地址中提取出来。
IP地址与网络掩码按位相与。则得到网络地址。

HostID每个bit置1. 则此IP即为网络内广播地址。

例如:
IP:  192.168.0.2.  MASK: 255.255.255.0
则广播地址:192.168.0.255

IP: 172.16.0.2   MASK: 255.255.0.0
广播地址:172.16.255.255

ifconfig中,会显示广播地址信息:
inet 10.0.0.2  netmask 255.255.255.0  broadcast 10.0.0.255

Sam认为这样说比较合适:
当向广播地址的某个端口发送数据报时,即相当于向本网内每个设备的这个端口发送数据报

2. 发送广播消息
要发送广播消息,需要两个基本条件。
a. 建立的socket 激活SO_BROADCAST选项。使socket endpoint成为一个可发送广播的socket.
b. 利用sendto(2) 向广播地址的特定port发送数据报。
也就是说:这个socket 必须能够进行广播。且目的地址必须为一个广播地址。


#include
#include          
#include
#include
#include
#include
#include
#include


int main(int argc, char** argv)
{
int iSocket_Send = 0;
int iRet = 0;
static int so_broadcast = 1;
char ip_Server[16] = {0};
struct sockaddr_in addr_server;
struct sockaddr_in addr_broadcast;
uint16_t port = 0;
char Message[36] = "Air raid this is not a drill";


iSocket_Send = socket(PF_INET, SOCK_DGRAM, 0);
if(iSocket_Send == -1)
{
perror("socket()");
return -1;
}

iRet = setsockopt(iSocket_Send, SOL_SOCKET, SO_BROADCAST, &so_broadcast, sizeof(so_broadcast));
if(iRet == -1)
{
perror("setsockopt()");
return -1;
}

memset(&addr_server, 0, sizeof(struct sockaddr_in));
strcpy(ip_Server, "10.0.0.2");

addr_server.sin_family = AF_INET;
addr_server.sin_port = htons(port);
inet_aton(ip_Server, (struct in_addr *)&addr_server.sin_addr);
#if 0
iRet = bind(iSocket_Send, (const struct sockaddr *)&addr_server, sizeof(struct sockaddr_in));
if(iRet == -1)
{
perror("bind()");
return -1;
}
#endif


memset(&addr_broadcast, 0, sizeof(struct sockaddr_in));
strcpy(ip_Server, "10.0.0.255");

addr_broadcast.sin_family = AF_INET;
addr_broadcast.sin_port = htons(9090);
inet_aton(ip_Server, (struct in_addr *)&addr_broadcast.sin_addr);
for(;;)
{
sendto(iSocket_Send, Message, strlen(Message), 0, (const struct sockaddr *)&addr_broadcast, sizeof(struct sockaddr_in));
sleep(1);
}

return 0;
}


3. 接收广播消息
理论上,接收广播消息和接收通常的UDP消息不应该有不同。就是接收指定Port上的数据。
#include
#include          
#include
#include
#include
#include
#include
#include

int main(int argc, char** argv)
{
int iSocket_Send = 0;
int iRet = 0;
uint16_t port = 9090;
struct sockaddr_in addr_local;
struct sockaddr_in addr_server;
char buffer[256] = {0};
socklen_t addr_len = 0;


iSocket_Send = socket(PF_INET, SOCK_DGRAM, 0);
if(iSocket_Send == -1)
{
perror("socket()");
return -1;
}


memset(&addr_local, 0, sizeof(struct sockaddr_in));

addr_local.sin_family = AF_INET;
addr_local.sin_port = htons(port);
addr_local.sin_addr.s_addr = htonl(INADDR_ANY);
iRet = bind(iSocket_Send, (const struct sockaddr *)&addr_local, sizeof(struct sockaddr_in));
if(iRet == -1)
{
perror("bind()");
return -1;
}


for(;;)
{
memset(buffer, 0, 256);
memset(&addr_server, 0, sizeof(struct sockaddr_in));
addr_len = sizeof(struct sockaddr_in);
iRet = recvfrom(iSocket_Send, buffer, 256, 0, (struct sockaddr *)&addr_server, &addr_len);
if(iRet == -1)
{
perror("recvfrom()");
continue;
}
printf("\nReceive Message from : [%s:%d].\n", inet_ntoa(addr_server.sin_addr), ntohs(addr_server.sin_port));
printf("\nMessage:[%s]. length:[%d]\n", buffer, iRet);

}


return 0;
}

但看了不少例子,在接收端,它是把广播地址绑定到接收socket上去。待未来研究


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有