多播与广播

本文详细介绍了多播和广播的概念及实现方式。多播能够跨网络传输数据,并且只需要发送一次即可让特定组内的所有接收者收到数据。广播则局限于同一网络内部,分为直接广播和本地广播两种类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多播:向加入特定组的大量主机以UDP的方式同时传送数据

 

特点

1、发送方只针对特定多播组发送一次数据

2、在特定多播组内所有接受者都会收到发往改组的数据

3、组数在IP(组播属于D类IP)地址范围内任意增加

4、基于UDP完成,多播数据包格式与UDP数据包相同

5、借助路由完成数据包的复制、传输(到主机)

 

设置TTL与加入多播组

要向使用多播必须设置TTL,TTL决定了数据包传递距离:数据包每经过一个路由器TTL就会减一,减到零时数据包无法被继续传递,会被销毁

注:TTL过大影响网络流量,过小可能无法传递到目标

 

ip_mreq结构体

struct ip_mreq 
{ 
	struct in_addr imr_multiaddr; //多播组的IP地址 
	struct in_addr imr_interface; //加入该组的套接字的所属主机IP地址,可使用INADDR_ANY 
}


 

 

发送方设置TTL

int  send_sock;
int time_live =  ttl大小;
…..
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, & time_live, sizeof(time_live));
….

 

接收方加入多播组

int recv_sock;
struct ip_mreq join_adr;
…
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
…
join_adr. imr_multiaddr.s_addr = 多播组IP;
join_adr. imr_interface.s_addr = 加入多播组的主机IP地址;
setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, & join_adr, sizeof(join_adr));
.....

示例代码:

 发送方

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define TTL 64    //决定数据包经过第64个路由时销毁
#define BUF_SIZE 30
void error_handling(const char *message);

int main(int argc, const char * argv[]) 
{
    int send_sock = -1;
    struct sockaddr_in mul_adr;
    int time_live = TTL;
    FILE *fp = NULL;
    char buf[BUF_SIZE] = { 0 };
	
    if( 3 != argc ) 
	{
        printf("Usage : %s <GroupIp> <Port> \n", argv[0]);
        exit(1);
    }

    send_sock = socket(PF_INET, SOCK_DGRAM, 0);//多播基于UDP
    memset(&mul_adr, 0, sizeof(mul_adr));
    mul_adr.sin_family = AF_INET;
    mul_adr.sin_addr.s_addr = inet_addr(argv[1]);	//此处需要设置数据目标为多播组IP地址
    mul_adr.sin_port = htons(atoi(argv[2]));		//目标端口

    setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&time_live, sizeof(time_live));//设置TTL

    if( NULL == (fp = fopen("./test.txt", "r")) )
        error_handling("fopen() error");

    while (!feof(fp)) //feof函数,文件结束返回非0值,否则返回0
    {
        fgets(buf, BUF_SIZE, fp);
        sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr *)&mul_adr, sizeof(mul_adr));
        sleep(1); //传输数据时间间隔,没有特殊意义
    }

    fclose(fp);
    close(send_sock);
    return 0;
}

void error_handling(const char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

接收方

 

#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(const char *message);

int main(int argc, const char * argv[]) 
{
    int recv_sock = -1;
    int str_len = -1;
    char buf[BUF_SIZE] = { 0 };
    struct sockaddr_in adr;	//绑定地址
    struct ip_mreq join_adr; //多播组结构地址相关

    if( 3 != argc ) 
    {
        printf("Usage : %s <GroupIp> <Port> \n", 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[2]));	//注意此处的端口必须与发送方的目标端口一致,之后的广播也一样

    if( -1 == bind(recv_sock, (struct sockaddr *)&adr, sizeof(adr)) )
        error_handling("bind() error");

    join_adr.imr_multiaddr.s_addr = inet_addr(argv[1]);	//多播组IP
    join_adr.imr_interface.s_addr = htonl(INADDR_ANY);	
    setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&join_adr, sizeof(join_adr));	//加入多播组

    while (1) 
	{
        str_len = recvfrom(recv_sock, buf, BUF_SIZE - 1, 0, NULL, 0);//不需要发送者地址信息,将最后两个参数分别设置为NULL与0
        if(str_len < 0)
            break;
        buf[str_len] = 0;
        fputs(buf, stdout);
    }

    close(recv_sock);
    return 0;
}


void error_handling(const char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}



广播

多播可以跨网络传输数据,只要加入了多播组,广播只能在同一网络中传输数据,广播也是基于UDP

 

广播分类

直接广播:广播的IP地址除网络地址外,主机地址全部设置为1,如向192.12.34中所有主机发送数据,可向192.12.34.255发送(一个是位,一个是点分十进制)

本地广播:广播的IP地址限定为255.255.255.255,如192.12.34网络中的主机向255.255.255.255发送数据,数据将传递到192.12.34网络中所有主机

 

套接字默认关闭广播,需要打开:

int  send_sock;
int bcast =  1;
…..
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, & bcast, sizeof(bcast));


注;只需要在发送方中打开广播,无需打开接收方,其他部分与普通UDP编程无异

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值