【TCP/IP】多播 - 定义、原理及编程实现(TTL、多播组、收发信息)

news2024/12/29 8:59:03

目录

多播

多播的原理

多播的数据传输时的特点

TTL 的概念

TTL 和 多播组的配置方法

多播的编程与实现

发送者

接收者


多播

        多播是一种介于单播和广播通信之间的技术方式,可以将发送者所需要发送的数据包分别发送给分散在不同子网中的一组接收者。

多播的原理

        多播的基础概念是“组”。一个多播组(multicast group)就是一组希望接收特定数据流的接收者,这个组没有物理或者地理的边界:组内的主机可位于互联网或者专用网络的任何地方。

        多播组中的每个节点被称为多播组成员(multicastgroupmember)。多播的数据传输协议基于UDP完成。采用多播方式时,可以同时向多个主机传递数据。

多播的数据传输时的特点

  • 多播服务器端针对特定多播组,只发送 1 次数据。
  • 即使只发送 1 次数据,但该组内的所有客户端都会接收数据。
  • 多播组数可在IP地址范围内任意增加。
  • 加入特定组即可接收发往该多播组的数据。 

        多播组的地址属于D类,即 224.0.0.0 ~ 239.255.255.255在发送多播数据包时(路由器得支持这项功能),需要有机器加入到多播组中以接收发来的数据包,同时路由器担负起将该数据包复制并传递到多个主机中的任务。如下图所示:

TTL 的概念

        传输多播数据包时,需要给程序设置TTL(TIme to Live 生存时间),这是决定数据包能否及时准确到达目标点的关键参数。

        TTL用整数表示,每经过1个路由器该数值便会减1。当TTL变为0时,该数据包将无法再被传递,作销毁处理。因此,在TTL的值上需要合理设置,过大会影响网络流量,过小将无法将数据包及时传递到目标。

TTL 和 多播组的配置方法

        在编程中,我们可以实现对 TTL 的设置。TTL相关的协议层为IPPROTO_IP,选项名为IP_MULTICAST_TTL,通过使用setsocketopt这个函数进行设置。

        代码如下:

int sock;
int ttl = 64;

sock = socket(PF_INET, SOCK_DGRAM, 0);
setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof(ttl));

        同样,加入到多播组也是通过 setsocketopt 函数完成。多播组加入的协议层为IPPROTO_IP,选项名为IP_ADD_MEMBERSHIP。 

        代码如下:

int recv_sock;
struct ip_mreq groupjoin_adr;

recv_sock = socket(PF_INET, SOCK_DGRAM, 0);

join_adr.imr_multiaddr.s_addr = "多播组的地址";
join_adr.imr_interace.s_addr = "加入多播组的主机地址";
setsockopt(recv_sock , IPPROTO_IP , IP_ADD_MEMBERSHIP , (void*) & groupjoin_adr), sizeof(groupjoin_adr));

        其中 ip_mreq 结构体,定义如下:

struct ip_mreq
  {
    /* 欲加入的多播组的地址.  */
    struct in_addr imr_multiaddr;

    /* 所属主机的IP地址. 可以使用INADDR_ANY  */
    struct in_addr imr_interface;
  };

多播的编程与实现

        多播中区分 发送者(Sender)接收者(Receiver)。发送者指的是发送多播数据的主体,接收者指的是位于多播组中的欲接收多播数据的主体。

发送者

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

#define TTL 64
#define BUF_SIZE 1024

void Sender_message(char *message)
{
	puts(message);
	exit(1);
}

int main(int argc, char *argv[])
{
	int send_sock;
	struct sockaddr_in mul_addr;
	int time2live = TTL;
	FILE *fp;
	char buf[BUF_SIZE];

	send_sock = socket(PF_INET, SOCK_DGRAM, 0);
	memset(&mul_addr, 0, sizeof(mul_addr));

	mul_addr.sin_family = AF_INET;
	mul_addr.sin_addr.s_addr = inet_addr(argv[1]); // 多播地址
	mul_addr.sin_port = htons(atoi(argv[2]));	   // 多播端口号

	setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&time2live, sizeof(time2live));

	fp = fopen(argv[3], "r");
	if (fp == NULL)
	{
		Sender_message((char*)"file open error");
	}

	while (!feof(fp)) /* 发送数据 */
	{
		fgets(buf, BUF_SIZE, fp);
		sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr *)&mul_addr, sizeof(mul_addr));
	}

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

接收者

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

#define BUF_SIZE 1024

//报错消息发送
void Sender_message(char *message)
{
    puts(message);
    exit(1);
}

int main(int argc, char *argv[])
{
    int recv_sock;
    int str_len;
    char buf[BUF_SIZE];
    struct sockaddr_in addr;
    struct ip_mreq join_addr;

    recv_sock = socket(PF_INET, SOCK_DGRAM, 0);
    memset(&addr, 0, sizeof(addr));

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(atoi(argv[2]));

    if (bind(recv_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    {
        Sender_message((char*)"bind error");
    }

    join_addr.imr_multiaddr.s_addr = inet_addr(argv[1]);
    join_addr.imr_interface.s_addr = htonl(INADDR_ANY);

    setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&join_addr, sizeof(join_addr));

    while (1)
    {
        // 接收多播数据 其中第五、第六个参数在不知道主机地址时可设为NULL和0
        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;
}

运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/680793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式软件架构——事务ACID

事务概念 事务处理几乎是每一个信息系统中都会涉及到的问题&#xff0c;它存在的意义就是保证系统中的数据是正确的&#xff0c;不同数据间不会产生矛盾&#xff0c;也就是保证数据状态的一致性&#xff08;Consistency&#xff09; 关于一致性&#xff0c;我们重点关注的是数…

ElasticSearch-安装Head可视化插件

安装Head可视化插件 首先需要依赖node.js和npm环境 1 安装node.js 官方下载地址:http://nodejs.cn/download/ 下载LTS版本&#xff08;长期稳定版本&#xff09; 安装可以更改安装路径,其余的都是选择 下一步傻瓜是安装 安装成功后如下 命令测试 node -v 查看node的版本 n…

理解redis的多线程和IO多路复用

参考资料 https://blog.csdn.net/TZ845195485/article/details/119745735 Redis单线程和多线程问题的背景 Redis里程碑版本迭代 Redis的单线程 主要是指Redis的网络IO和键值对读写是由一个线程来完成的&#xff0c;Redis在处理客户端的请求时包括获取&#xff08;socket读&a…

「实验记录」MIT 6.824 KVRaft Lab3A Without Log Compaction

#Lab3A - KVRaft without log compaction I. SourceII. My CodeIII. MotivationIV. SolutionS1 - client请求S2 - server回应 V. Result I. Source MIT-6.824 2020 课程官网Lab3: KVRaft 实验主页simviso 精品付费翻译 MIT 6.824 课程Paper - Raft extended version II. My C…

Python顺序结果、选择结构、循环结构(超详细讲解+多段代码案例)

我本微末凡尘&#xff0c;可也心向天空 文章目录 一、顺序结构 二、选择结构 1.if----elif----else语句 2.条件表达式 三、循环结构 1.range函数 2.while 循环 3. for----in 循环 四、continue、break在循环中的使用 大家好&#xff0c;我是纪宁 今天要介绍的是python…

fatal error: ‘type_traits‘ file not found错误解决

错误如下 In file included from ../test_opencv_qt/main.cpp:1: In file included from ../../Qt/6.5.1/android_x86_64/include/QtGui/QGuiApplication:1: In file included from ../../Qt/6.5.1/android_x86_64/include/QtGui/qguiapplication.h:7: In file included from .…

Nginx 限流算法大揭秘

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

01 | 一条 SQL 查询语句是如何执行的?

以下内容出自 《MySQL 实战 45 讲》 一条 SQL 查询语句是如何执行的&#xff1f; 下面是 MySQL 的基本架构示意图&#xff0c;从中可以清楚地看到 SQL 语句在 MySQL 的各个功能模块中的执行过程。 大体来说&#xff0c;MySQL 可以分为 Server 层和存储引擎层两部分。 Server …

leetcode188. 买卖股票的最佳时机 IV.动态规划-java

买卖股票的最佳时机 IV leetcode188. 买卖股票的最佳时机 IV题目描述 动态规划代码演示 动态规划专题 leetcode188. 买卖股票的最佳时机 IV 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/best-time-to-buy-and-sell-st…

DatenLord前沿技术分享 No.28

达坦科技专注于打造新一代开源跨云存储平台DatenLord&#xff0c;通过软硬件深度融合的方式打通云云壁垒&#xff0c;致力于解决多云架构、多数据中心场景下异构存储、数据统一管理需求等问题&#xff0c;以满足不同行业客户对海量数据跨云、跨数据中心高性能访问的需求。在本周…

Reentrantreadwritelock应用和原理

目录 一、介绍 二、应用 三、原理 一、介绍 当读操作远远高于写操作时&#xff0c;这时候使用读写锁让读-读可以并发&#xff0c;提高性能 类似于数据库中的共享锁 select...from...lock in share mode 提供一个数据容器类内部分别使用读锁保护数据的read()方法&#x…

Android 9-SystemUI:(1)启动流程

具体分析(以下代码示例&#xff0c;讲解&#xff0c;都是通过&#xff0c;Android9代码来举例&#xff09; SystemUI,其实是可以看作是一个系统级的服务&#xff0c;也就是SystemUIService, SystemUI的服务启动&#xff0c;要从SystemServer.run()方法入手 main 方法里启动了…

JavaWeb小记—响应对象response

目录 响应对象response的原理图 response——响应对象 响应文本数据 响应字节数据 验证码案例 响应状态码 1.http状态返回代码 1xx&#xff08;临时响应&#xff09; 2.http状态返回代码 2xx &#xff08;成功&#xff09; 3.http状态返回代码 3xx &#xff08;重定向…

2023.6.12-6.18 AI行业周刊(第151期):AI创业项目交付部署,困难和机遇并存

这段时间&#xff0c;工作上项目上的事情&#xff0c;开始进入了一个快车道&#xff0c;很多项目开始并行。所以每天白天的时候&#xff0c;被各种事情填充的很满。 加入华勤后从0到1组建的团队&#xff0c;其实本身也是创业属性&#xff0c;从市场->售前->算法->视频…

Godot 4 源码分析 - 练手 - 和谐共生

今天看到一个微信视频&#xff0c;和谐共生&#xff0c;大概效果如下 https://live.csdn.net/v/306826 研究这么长时间的Godot&#xff0c;今天试试能否实现上述效果 粗看一下&#xff0c;这个效果实现分几步&#xff1a; 1. 画圆&#xff0c;并确定多个圆的位置规律 2. 动…

UE4/5动画系列(2.怎么套模板)

目录 大象套模板 动画同步&#xff08;这个在模板里面开同步&#xff09;&#xff1a; 速度限制&#xff1a; 穿墙问题&#xff1a; 在之前我们已经做了一个基础的模板了&#xff1a; UE4/5动画蓝图模板制作和套模板&#xff08;1.模板制作&#xff09;_多方通行8的博客-C…

【计算机组成原理】总线

目录 一、总线概述 二、总线的分类 三、系统总线的结构 四、总线的性能指标 五、总线仲裁 六、总线操作和定时 七、总线标准 一、总线概述 总线&#xff1a;是一组能为多个部件分时共享信息的传送线路 早期计算机外部设备少时大多采用分散连接方式&#xff0c;不易实现…

【C语言初阶】带你轻松玩转所有常用操作符(1)

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,这里是君兮_&#xff0c;最近要准备期末复习了&#xff0c;可能更新的就不会那么频繁了&#xff0c;下个星期回复正常更新。 操作符详解1 前言一.操作符的分类二.算数操作符三.移位操作符1.二进制表示的三种形式2.…

【C/C++】构造函数与析构函数

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

【话题研究】重塑活力:顺应消费需求变化,PC市场需创新、技术驱动和营销策略更优解

话题研究&#xff1a;大众还需要PC吗&#xff1f;PC市场如何走出寒冬&#xff1f; 1️⃣ PC市场进入寒冬的深层原因2️⃣ PC仍具有独特的优势和不可替代性3️⃣ 创新、定制化和用户体验4️⃣ AI、VR时代带来的新出路 市场调研机构 Canalys数据显示&#xff0c;今年一季度&#…