java|网络编程(20)—— 广播的编程实现

一、广播和多播的区别 广播是向同一网络中所有主机传播数据的一种方式。它和多播的主要区别在于:
1、从范围上来说,多播即使在跨越不同网络的情况下,只要加入多播组就能接受数据。而广播只能向同一网络中的主机传输数据(这种网络可以是发送者所在的网络,也可以是发送者所在网络之外的网络)。
2、从接受者的角度来说,接受者在多播中是主动的,接收端需要主动加入多播组,然后才能接受数据。而广播中,对接受者无特别的要求,只要在发送端的目标网络,主机即可接受广播数据。
二、广播的分类 广播分为两种,直接广播和本地广播。二者的主要差别:
1、从目标网络方面,直接广播的目标网络和发送端不在同一个网络,本地广播的目标网络就是发送端本机所在的网络。
【java|网络编程(20)—— 广播的编程实现】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
**
克隆本项目:
gitclonegit@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
gitcheckout NL20

    推荐阅读