广播是向同一网络中所有主机传播数据的一种方式。它和多播的主要区别在于:
1、从范围上来说,多播即使在跨越不同网络的情况下,只要加入多播组就能接受数据。而广播只能向同一网络中的主机传输数据(这种网络可以是发送者所在的网络,也可以是发送者所在网络之外的网络)。
2、从接受者的角度来说,接受者在多播中是主动的,接收端需要主动加入多播组,然后才能接受数据。而广播中,对接受者无特别的要求,只要在发送端的目标网络,主机即可接受广播数据。
广播分为两种,直接广播和本地广播。二者的主要差别:
1、从目标网络方面,直接广播的目标网络和发送端不在同一个网络,本地广播的目标网络就是发送端本机所在的网络。
2、从P地址上来说,直接广播的IP地址,除了网络地址外,其余主机地址全部设置为1.如希望向网络地址192.168.5的所有主机传输数据时,发送端的目标ip要设置为192.168.5.255传输。而本地广播中使用的IP地址限定为255.255.255.255.如,192.5.24网络中的主机向255.255.255.255传输数据时,数据将传递到192.5.24网络中的所有主机。
广播也是基于UDP协议的实现,其与普通UDP传输的区别,一是通信中使用的IP地址不同,二是需要使用setsockopt()函数设置socket支持多播的选项。
int send_sock;
int bcast = 1;
....
send_sock=socket(PF_INET,SOCK_DGRAM,0);
....
setsockopt(send_sock,SOL_SOCKET,SO_BROADCAST,(void*)&bcast,sizeof(bcast));
我们在发送端实现类似上一文中的功能,读取本地的news.txt文件的内容,然后以广播的方式传递给所有的接受端,代码如下:
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 30
void error_handling(char* message);
int main(int argc,char* argv[])
{
int send_sock;
struct sockaddr_in broad_adr;
FILE *fp;
char buf[BUF_SIZE];
int so_brd=1;
if(argc!=3)
{
printf("Usage : %s
",argv[0]);
exit(1);
}
send_sock=socket(PF_INET,SOCK_DGRAM,0);
memset(&broad_adr,0,sizeof(broad_adr));
broad_adr.sin_family=AF_INET;
broad_adr.sin_addr.s_addr=inet_addr(argv[1]);
broad_adr.sin_port=htons(atoi(argv[2]));
setsockopt(send_sock,SOL_SOCKET,
SO_BROADCAST,(void*)&so_brd,sizeof(so_brd));
if((fp=fopen("news.txt","r"))==NULL)
{
error_handling("fopen error");
}
while(!feof(fp))
{
fgets(buf,BUF_SIZE,fp);
sendto(send_sock,buf,strlen(buf),
0,(struct sockaddr*)&broad_adr,sizeof(broad_adr));
sleep(2);
}
close(send_sock);
return 0;
}
void error_handling(char* message)
{
fputs(message,stderr);
fputc('
',stderr);
exit(0);
}
第11行,我们定义了一个整形的变量so_brd并设置为1,作为socket的设置选项。
第31行,通过setsockopt()函数设置socket的SO_BROADCAST为1,该套接字就变成了一个多播的套接字。
如果我们想要使用本地方式发送广播的数据,那么应该把目标地址设置成255.255.255.255,如:
./serv 255.255.255.255 8888
如果我们想要使用直接广播的方式发送数据,比如向所有网络地址为192.168.80.0的主机发送数据,则需要按照下面的方式:
./serv 192.168.80.255 8888
接收端就是普通的UDP接受端,这里不再解释:
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 30
void error_handling(char* message);
int main(int argc,char* argv[])
{
int recv_sock;
struct sockaddr_in adr;
int str_len;
char buf[BUF_SIZE];
if(argc!=2)
{
printf("Usage : %s
",argv[0]);
exit(1);
}
recv_sock=socket(PF_INET,SOCK_DGRAM,0);
memset(&adr,0,sizeof(adr));
adr.sin_family=AF_INET;
adr.sin_addr.s_addr=htonl(INADDR_ANY);
adr.sin_port=htons(atoi(argv[1]));
if(bind(recv_sock,(struct sockaddr*)&adr,sizeof(adr))==-1)
error_handling("bind error");
while(1)
{
str_len=recvfrom(recv_sock,buf,BUF_SIZE-1,0,NULL,0);
if(str_len<0)
break;
buf[str_len]=0;
fputs(buf,stdout);
}
close(recv_sock);
return 0;
}
void error_handling(char* message)
{
fputs(message,stderr);
fputc('
',stderr);
exit(0);
}
Github位置:
**https://github.com/HymanLiuTS/NetDevelopment
**
克隆本项目:
[email protected]:HymanLiuTS/NetDevelopment.git
获取本文源代码:
gitcheckout NL20