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

news2024/9/21 1:15:46

目录

多播

多播的原理

多播的数据传输时的特点

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/698063.html

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

相关文章

MySQL - 第11节 - MySQL事务管理

1.事务的概念 事务的概念&#xff1a; • 上层看起来比较简单的需求&#xff0c;可能对应的后端要做很多工作&#xff0c;后端这些工作组合起来才是一个完整的需求解决的方案。 • 事务由一条或多条SQL语句组成&#xff0c;这些语句在逻辑上存在相关性&#xff0c;共同完成一个…

聊聊transformers库; 微软推出ZeRO++技术:优化大型AI模型训练时间和成本

&#x1f989; AI新闻 &#x1f680; 微软推出ZeRO技术&#xff1a;优化大型AI模型训练时间和成本 摘要&#xff1a;据报道&#xff0c;微软研究人员最近发布了一项名为ZeRO的新技术&#xff0c;旨在优化训练大型AI模型时常遇到的数据传输成本和带宽限制问题&#xff0c;可大…

【0212】tcpdump抓包分析pg_hba.conf以password作为认证证方式下frontend与Backend之间身份验证过程(13 - 2)

文章目录 1. 回顾2. 密码校验通过3. 密码校验失败上一文:【0211】tcpdump抓包分析pg_hba.conf以password作为认证证方式下frontend与Backend之间身份验证过程(13 - 1) 1. 回顾 在上一节内容中,讲解了Backend对于接收到来自frontend的字符串明文密码,和来自于来自pg_auth…

荷兰宽带数据泄露 1

又要引入一个新工具RouterPassView 大多数现代路由器都可以备份一个路由器的配置文件&#xff0c;然后在需要的时候从文件中恢复配置。路由器的备份文件通常包含了像您的ISP的用户名重要数据/密码&#xff0c;路由器的登录密码&#xff0c;无线网络的KEY。 如果你忘记了这些密码…

第八十九天学习记录:C++核心:引用

引用的基本使用 作用&#xff1a;给变量起别名 语法&#xff1a;数据类型 &别名原名 #include<iostream> using namespace std;int main() {//引用基本语法//数据类型 &别名 原名int num1 3;int &num2 num1;cout << "num1" << n…

输入路由器IP地址进入IIS问题解决

0x01 问题描述 Windows10系统&#xff0c;路由器IP为192.168.1.1&#xff0c;本机获取的IP为192.168.1.110&#xff0c;但在浏览器URL输入路由器IP时却没有进入路由登录页&#xff0c;而是进了IIS欢迎页面。 0x02 问题分析 由于我本机IP不是192.168.1.1&#xff0c;所以排除与…

第八十七天学习记录:Linux基础:基础指令Ⅱ

touch创建文件 可以通过touch命令创建文件 语法&#xff1a;touch Linux路径 1、touch命令无选项&#xff0c;参数必填&#xff0c;表示要创建的文件路径&#xff0c;相对、绝对、特殊路径符均可以使用 cat命令 查看文件内容 首先用Vim编辑器在刚刚新建的tanktest.txt中编辑…

MyBatis学习笔记--中篇

MyBatis学习 文章目录 MyBatis学习1、MyBatis 配置解析1.1、核心配置文件1.2、事务管理器&#xff08;transactionManager&#xff09;1.3、数据源&#xff08;DataSource&#xff09;1.4、属性&#xff08;properties&#xff09;1.5、类型别名&#xff08;typeAliases&#x…

1. AGPC-SLAM: Absolute Ground Plane Constrained 3D Lidar SLAM

AGPC-SLAM: Absolute Ground Plane Constrained 3D Lidar SLAM overview 关键思路 odom约束 回环检测约束 地面约束 总体约束 问题 地面约束似乎倾向于全部对齐到第一个平面&#xff0c;也就是说该方案假设了所有地面方程是同一个平面。后面的实验也验证了上述假设有问题&…

EfficientDet(EfficientNet+BiFPN)论文超详细解读(翻译+学习笔记+代码实现)

前言 在之前我们介绍过EfficientNet&#xff08;直通车&#xff1a;【轻量化网络系列&#xff08;6&#xff09;】EfficientNetV1论文超详细解读&#xff08;翻译 &#xff0b;学习笔记代码实现&#xff09; 【轻量化网络系列&#xff08;7&#xff09;】EfficientNetV2论文超详…

Linux:etc/group

etc/group文件中保存着系统中所有组的名称&#xff0c;以及每个组中的成员列表。 文件中的一行为一个组的信息&#xff0c;具体如下&#xff1a; 如果组口令字段为x的话&#xff0c;就还有一个etc/gshadow文件用于存放组口令。 GID用于标识一个组&#xff0c;应保证其唯一性。…

Spring Boot 中的事务回滚规则

Spring Boot 中的事务回滚规则 在应用程序中&#xff0c;事务管理是一个重要的概念。事务是指一系列的操作&#xff0c;这些操作要么全部成功&#xff0c;要么全部失败。在Spring Boot中&#xff0c;我们可以使用事务管理器来管理事务。在使用事务管理器的时候&#xff0c;一个…

ElasticSearch——复合查询

Elasticsearch 语雀&#xff08;完整笔记&#xff09; 复合&#xff08;compound&#xff09;查询&#xff1a;复合查询可以将其它简单查询组合起来&#xff0c;实现更复杂的搜索逻辑。常见的有两种&#xff1a; fuction score&#xff1a;算分函数查询&#xff0c;可以控制…

《计算机系统与网络安全》第七章 身份认证

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【单片机】STM32单片机读取旋转编码器,TIM定时器捕获

文章目录 旋转编码器介绍主程序逻辑直接检测用外部中断检测下降沿定时器直接解码旋转编码器 旋转编码器介绍 旋转编码器简单来说&#xff0c;就是会输出2个PWM&#xff0c;依据相位可以知道旋转方向&#xff0c;依据脉冲个数可以知道旋转的角度。一般旋转一圈有一个固定数值的…

chatgpt赋能python:Python输出\n的用法及优势

Python 输出\n 的用法及优势 在Python编程语言中&#xff0c;我们常常需要输出字符串&#xff0c;并在特定地方换行。在这种情况下&#xff0c;使用\n是一种非常方便的方式。在本文中&#xff0c;我们将详细介绍Python的输出\n的用法及其优势。 什么是\n&#xff1f; \n是一…

Spark17-18-19

17. Spark执行流程 17.1 创建SparkContext 使用spark-submit脚本&#xff0c;会启动SparkSubmit进程&#xff0c;然后通过反射调用我们通过--class传入类的main方法&#xff0c;在main方法中&#xff0c;就行我们写的业务逻辑了&#xff0c;先创建SparkContext&#xff0c;向M…

YOLOv5-7.0添加BottleNet transformer

YOLOv5主干特征提取网络为CNN网络&#xff0c;CNN具有平移不变性和局部性&#xff0c;缺乏全局建模长距离建模的能力&#xff0c;引入自然语言领域的Transformer可以形成CNNTransFormer架构&#xff0c;充分结合两者的优点&#xff0c;提高目标检测效果。 1. BoTNet 论文地址…

BeautifulSoup爬取豆瓣电影数据

BeautifulSoup爬取豆瓣TOP250 豆瓣爬取地址 https://movie.douban.com/top250?formattext BeautifulSoup官网地址 https://www.rddoc.com/doc/BeautifulSoup/4.5.3/zh/quick-start/ 安装所需函数库 pip install beautifulsoup4pip install lxmlpip install requests导入…

IIS安装localhost显示下载,urlrewrite设置

1.取消ftp服务勾选 2. ping localhost ping 127.0.0.1 如果显示 &#xff1a;&#xff1a;1 则需要禁用ipv6 在注册表 找到并单击下面的注册表子项&#xff1a; HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters\ 双击“DisabledComponents”以修…