组播(UDP)

1.UDP协议

学习组播就必须先了解UDP。UDP(用户数据报协议,User Datagram Protocol)是一种传输层协议,属于TCP/IP协议族的一部分。它提供了一种简单而高效的方式来在网络上发送数据,但与TCP(传输控制协议)相比,UDP提供的服务具有不同的特征和优势。

UDP的特点:

1.无连接:UDP是一个无连接协议,这意味着在发送数据之前不需要建立连接。这种特性使得UDP在数据传输时不需要建立和维护连接状态,减少了开销和延迟。

2.不可靠:UDP不保证数据报的传递。顺序或者完整性。数据报可能丢失,重复或者乱序到达。UDP不提供重传机制,也不进行错误检查或纠正。

3.低延迟:由于没有建立连接,确认和重传机制,UDP传输数据时的延迟较低,适用于对实时性要求较高的场景。

4.简单:UDP的包头非常简单,仅包含少量的字段,使它的处理和开销比TCP小。

5.数据报服务:UDP以数据报(datagram)形式发送数据,每个数据报都是一个独立的消息,发送端和接收端不需要保持状态信息。

使用场景包括但不限于(在线游戏,视屏会议,以及组播)。

代码示例:使用udp建立客户端与服务端连接

udp_server.cpp

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 12345
#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in servaddr, cliaddr;
    char buffer[BUFFER_SIZE];
    socklen_t len = sizeof(cliaddr);

    // 创建套接字
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        std::cerr << "Socket creation failed" << std::endl;
        return 1;
    }

    // 填充服务器地址结构
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = INADDR_ANY;
    servaddr.sin_port = htons(PORT);

    // 绑定套接字
    if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        std::cerr << "Bind failed" << std::endl;
        return 1;
    }

    while (true) {
        // 接收数据
        int n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, 0, (struct sockaddr *)&cliaddr, &len);
        buffer[n] = '\0';
        std::cout << "Received message: " << buffer << std::endl;

        // 回复客户端
        std::string response = "Message received";
        sendto(sockfd, response.c_str(), response.length(), 0, (const struct sockaddr *)&cliaddr, len);
    }

    close(sockfd);
    return 0;
}

upd_cliect.cpp

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 12345
#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in servaddr;
    char buffer[BUFFER_SIZE];

    // 创建套接字
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        std::cerr << "Socket creation failed" << std::endl;
        return 1;
    }

    // 填充服务器地址结构
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servaddr.sin_port = htons(PORT);

    // 发送数据
    std::string message = "Hello, UDP server!";
    sendto(sockfd, message.c_str(), message.length(), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr));

    // 接收响应
    int n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, 0, NULL, NULL);
    buffer[n] = '\0';
    std::cout << "Server response: " << buffer << std::endl;

    close(sockfd);
    return 0;
}

运行结果:

2.什么是组播

组播(Multicast)是一种允许数据从源地址发送到多个目标地址的通信方式,它介于单播和广播之间。组播数据报并不是基于IP数据报的目的地址,而是通过RTF(Reverse Path Forwarding)逆向路径转发的方式转发数据包,确保数据只发送到需要接受的组播组成员。组播提高了数据传输效率,减少了骨干网络出现拥塞的可能性,特别适用于一对多的通信场景。

3.组播,单播,广播之间的区别

单播:一对一的通信方式,即一个发送方传输数据到一个接收方,每个数据包都有唯一的目的地址。如果有多个接受者,每个接受者都需要一个独立的副本,会导致带宽的重复消耗。通常使用点对点传输(网页,文件传输和电子邮件)。

广播:一对全(数据被发送到网络中的所有设备)广播地址IPv4(255.255.255.255),广播会消耗整个网络的带宽,所有设备都需要对广播发出的这包数据进行处理,即使有些设备并不需要。通常用于需要再同一网络内的所有设备之间传递信息的场景,如ARP请求(地址解析协议)或者局域网内的服务发现。

4.IPv4组播地址的取值范围

为了使组播源和组播组员进行通信,需要提供网络层组播使用的IP组播地址。IANA(Internet Assigned Numbers Authority)负责管理和分配互联网协议资源的组织将D类地址空间分配给IPv4组播使用,IPv4地址一共32位,D类地址最高4位为1110,地址范围从224.0.0.0到239.255.255.255,。

地址范围

含义

224.0.0.0~224.0.0.255

永久组地址。IANA为路由协议预留的IP地址(也称为保留组地址),用于标识一组特定的网络设备,供路由协议、拓扑查找等使用,不用于组播转发。

224.0.1.0~231.255.255.255

233.0.0.0~238.255.255.255

ASM组播地址,全网范围内有效。

说明:

其中,224.0.1.39和224.0.1.40是保留地址,不建议使用。

232.0.0.0~232.255.255.255

缺省情况下的SSM组播地址,全网范围内有效。

239.0.0.0~239.255.255.255

本地管理组地址,仅在本地管理域内有效。在不同的管理域内重复使用相同的本地管理组地址不会导致冲突。

常见的永久组地址

永久组地址

含义

224.0.0.0

不分配

224.0.0.1

网段内所有主机和路由器(等效于广播地址)

224.0.0.2

所有组播路由器

224.0.0.3

不分配

224.0.0.4

DVMRP(Distance Vector Multicast Routing Protocol,距离矢量组播路由协议)路由器

224.0.0.5

OSPF(Open Shortest Path First,开放最短路径优先)路由器

224.0.0.6

OSPF DR(Designated Router,指定路由器)

224.0.0.7

ST(Shared Tree,共享树)路由器

224.0.0.8

ST主机

224.0.0.9

RIP-2(Routing Information Protocol version 2,路由信息协议版本2)路由器

224.0.0.11

移动代理(Mobile-Agents)

224.0.0.12

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)服务器/中继代理

224.0.0.13

所有PIM(Protocol Independent Multicast,协议无关组播)路由器

224.0.0.14

RSVP(Resource Reservation Protocol,资源预留协议)封装

224.0.0.15

所有CBT(Core-Based Tree,有核树)路由器

224.0.0.16

指定SBM(Subnetwork Bandwidth Management,子网带宽管理)

224.0.0.17

所有SBM

224.0.0.18

VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)

224.0.0.22

所有使能IGMPv3(Internet Group Management Protocol, Version 3,因特网组管理协议)的路由器

224.0.0.19 ~ 224.0.0.21

224.0.0.23 ~ 224.0.0.255

未指定

5.IPv4组播MAC地址

以太网传输IPv4单播报文的时候,目的MAC地址使用的是接受者的MAC地址。但是在传输组播数据时,其目的地不再是一个具体的接受者,而是一个成员不确定的组,所以要使用IPv4组播MAC地址,即IPv4组播地址映射到链路层中的地址。

IANA规定,IPv4组播MAC地址的高24位为0x01005e,第25位为0,低23位为IPv4组播地址的低23位。

例如:IPv4组播地址224.1.2.3

转化IPv4的二进制

224.1.2.3 ==> 11100000.00000001.00000010.00000011

提取低23位

00000010.00000011(2.3)

组播MAC地址

MAC地址格式:01:00:5E:xx:xx:xx

结合IPv4的低23位,得到的MAC地址为:01:00:5E:01:02:03

注:IPv4组播地址映射到MAC地址的方式确保了再以太网中,组播数据包能够正确地送到所有订阅了特定组的设备。组播MAC地址的前缀01:00:5E表示该地址用于组播目的。

6.组播协议包解析

组播协议包的解析涉及不同的网络协议层和数据结构,主要包含数据链路层。网络层和传输层。

1.数据链路层

在以太网数据链路层,组播层的目标地址是一个组播MAC地址,通常以01:00:5E:xx:xx:xx的形式表示。数据链路层的组播包包含以下字段:

目的MAC地址:组播MAC地址,例如 01:00:5E:00:00:01
源MAC地址:发送者的MAC地址
以太网类型字段:指示上层协议类型,如IPv4或IPv6.

2.网络层(IPv4)

在网络层,组播包的 IP 地址是在 IPv4 组播地址范围内。IPv4 组播地址的范围是 224.0.0.0239.255.255.255。IPv4 组播数据包的格式如下:

版本:4位,表示IPv4.
头部长度:4位,表示IPV头部长度。
服务类型:8位,表示服务质量
总长度:16位,表示整个数据包的长度。
标识符,标志和片偏移:用于数据包的分片和重组。
生存时间(TTL):8位,控制数据包的生命周期。TTL为1的数据包不会被转发,适用于本地组播。
协议:8位,表示上层协议,如UDP.
源IP地址:发送者的IPv4地址。
目的IP地址:组播地址。

3.传输层(UDP)

在传输层,组播数据通常使用UDP,因为它提供了简单的无连接服务,适合组播流量。UDP头部的格式如下:

源端口:16位,发送方的端口号。
目的端口:16位,接收方的端口号。
长度:16位,UDP数据报的长度(包括头部的数据)。
校验位:16位,用于检查UDP数据包的完整性。

4.应用层

在应用层,组播协议包的解析依赖于具体的应用协议。;例如,应用层可能使用以下协议:

IGMP(Internet Group Management Protocol):用于管理主机加入或离开组播组。IGMP报文在IP头部之后直接跟随,紫萼不使用UDP。
PIM(Protocol IndepenDent MuIticast):用于组播路由的协议。PIM包含在IP数据包中,但其具体的报文格式和解析涉及更多细节。