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

一、广播和多播的区别

广播是向同一网络中所有主机传播数据的一种方式。它和多播的主要区别在于:

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<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>

#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 <Boradcast IP> <PORT>
",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<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>

#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 <port> 
",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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值