第十篇:Linux 组播socket通讯中指定组

跨平台(Windows+Linux)的Socket通讯程序(一)—底层封装 【摘要】编写Socket通讯程序是一个老话题。本文重点介绍Windows平台和Linux平台Socket通讯的不同,采用C++,编制了一个简单的跨平台的Socket通讯库。 一、Socket通讯的基础知识 Socket通讯是两个计算机之间最基本的通讯方法,有TCP和UDP两种协议。关于这两种协议的区别,不少文章已有详述,这里,稍微总结一下: 1.TCP是面向连接的,是“流”式的,意即通讯两端 阅读详情

视频会议、实时股票报价都应用到组播通讯。多播通信通常用于需要将数据同时发送给多个接收者的场景。

组播,顾名思义,即是组内成员广播。

首先当然是要定义组、加入组的了。

发送的时候,sendto 的地址参数上,就能直接设置组信息。

接受某个组的时候要单独进行设置。

下面2个数据结构与函数完成用于完成该工作。

  • struct ip_mreq
  • setsockopt()

struct ip_mreq 是一个结构体,用于指定多播(Multicast)通信中的多播组IP地址和本地网络接口地址。这个结构体通常与 setsockopt() 函数一起使用,以加入一个多播组。

以下四个步骤完整这个设置。

  1. 定义 struct ip_mreq 结构体:

struct ip_mreq
{
    struct in_addr imr_multiaddr;   /* 指定多播组IP */
    struct in_addr imr_interface;   /* 本地网卡地址,通常指定为 INADDR_ANY (0.0.0.0) */
};
它包含两个 struct in_addr 类型的成员:imr_multiaddr 用于存储多播组的IP地址,imr_interface 用于存储本地网络接口的地址。

  2、使用前要声明并初始化 struct ip_mreq 变量:

struct ip_mreq mreq;
bzero(&mreq, sizeof(mreq));

                使用 bzero() 函数将其内存区域清零。bzero() 函数将指定大小的内存区域设置为零,这里的大小是 sizeof(mreq),即 struct ip_mreq 结构体的大小。


3、设置多播组地址和本地网络接口地址:

mreq.imr_multiaddr.s_addr = inet_addr("224.10.10.1");
mreq.imr_interface.s_addr = INADDR_ANY;
这里将多播组的IP地址设置为 224.10.10.1,这是一个有效的多播地址。本地网络接口地址被设置为 INADDR_ANY,表示程序将在所有可用的网络接口上监听多播数据。
4、调用 setsockopt() 函数加入多播组:
setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

这里调用 setsockopt() 函数,将套接字 sockfd 加入到之前指定的多播组。IPPROTO_IP 表示使用IPv4协议,IP_ADD_MEMBERSHIP 是用于加入多播组的选项。&mreq 是指向 struct ip_mreq 变量的指针,sizeof(mreq) 是结构体的大小。

我们的目的是将一个套接字加入到指定的多播组,以便能够接收发送到该多播组的数据。

多播地址的规则:

  1. 地址范围:
    • IPv4中的多播组地址范围是从224.0.0.0到239.255.255.255。
  2. 地址格式:
    • 多播组地址的前4位固定为“1110”,这是多播地址的标识。
    • 剩余的28位用于标识特定的多播组。
  3. 地址类型:
    • 多播组地址可以分为全球唯一地址和本地唯一地址。
    • 全球唯一地址可以在全球范围内使用,而本地唯一地址则限制在特定的网络或组织内使用。
  4. 特殊地址:
    • 某些多播组地址被指定为特殊用途,如224.0.0.1用于本子网上所有参加多播的主机和路由器,224.0.0.2用于本子网上所有参加多播的路由器等。
  5. 地址分配:
    • 多播组地址的使用和分配现在由互联网地址指派机构(IANA)控制。

IPv6中的多播组地址规则

  1. 地址前缀:
    • IPv6中的多播组地址以FF00::/8为前缀。
  2. 地址格式:
    • 多播组地址的前8位固定为“FF”,这是多播地址的标识。
    • 剩余的位数用于标识特定的多播组。
  3. 地址类型:
    • 与IPv4类似,IPv6中的多播组地址也可以分为全球唯一地址和本地唯一地址。
  4. 特殊地址:
    • 某些多播组地址在IPv6中也有特殊的用途,如FF02::1是所有设备都可以加入的广播地址。

其他:

  • 在配置网络以支持多播时,应确保网络设备(如路由器和交换机)支持多播协议,并正确配置了多播路由和转发规则。

一个完整演示的demo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <netinet/in.h>
#include <sys/time.h> // for settimeofday, though not used directly here

#define MULTICAST_ADDR "239.255.255.250"
#define MULTICAST_PORT 12345
#define BUFFER_SIZE 1024

void* send_multicast_message(void* arg) {
    int sockfd = *((int*)arg);
    const char* message = "Hello, Multicast!";
    struct sockaddr_in multicast_addr;

    memset(&multicast_addr, 0, sizeof(multicast_addr));
    multicast_addr.sin_family = AF_INET;
    multicast_addr.sin_port = htons(MULTICAST_PORT);
    inet_pton(AF_INET, MULTICAST_ADDR, &multicast_addr.sin_addr);

    while (1) {
        sendto(sockfd, message, strlen(message), 0,
               (struct sockaddr*)&multicast_addr, sizeof(multicast_addr));
        printf("Sent: %s\n", message);
        sleep(1);
    }
    return NULL;
}

void* receive_multicast_message(void* arg) {
    int sockfd = *((int*)arg);
    char buffer[BUFFER_SIZE];
    struct sockaddr_in src_addr;
    socklen_t addr_len = sizeof(src_addr);

    while (1) {
        int num_bytes = recvfrom(sockfd, buffer, BUFFER_SIZE, 0,
                                 (struct sockaddr*)&src_addr, &addr_len);
        if (num_bytes > 0) {
            buffer[num_bytes] = '\0';
            printf("Received from %s: %s\n", inet_ntoa(src_addr.sin_addr), buffer);
        }
    }
    return NULL;
}

int main() {
    int sockfd;
    struct sockaddr_in local_addr;
    pthread_t sender_thread, receiver_thread;

    // 创建UDP套接字
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    int allow = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
                   &allow, sizeof(allow)) < 0) {
        perror("setsockopt");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 绑定套接字到本地地址和端口(可选,但推荐)
    memset(&local_addr, 0, sizeof(local_addr));
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    local_addr.sin_port = htons(MULTICAST_PORT);

    if (bind(sockfd, (const struct sockaddr*)&local_addr, sizeof(local_addr)) < 0) {
        perror("bind failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 允许接收组播消息
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDR);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);

    if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) < 0) {
        perror("setsockopt");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 启动发送和接收线程
    if (pthread_create(&sender_thread, NULL, send_multicast_message, &sockfd) != 0) {
        perror("pthread_create sender failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    if (pthread_create(&receiver_thread, NULL, receive_multicast_message, &sockfd) != 0) {
        perror("pthread_create receiver failed");
        close(sockfd);
        pthread_cancel(sender_thread); // 尝试取消已创建的发送线程
        exit(EXIT_FAILURE);
    }

    // 注意:在纯C中,我们通常不会在这里等待线程完成,因为它们是无限循环的。
    // 如果需要终止程序,应该使用某种信号或全局变量来控制线程的退出。
    // 这里为了示例,我们让主线程也无限等待(不推荐在实际应用中使用)。
    // 通常,你会在另一个线程或信号处理程序中设置某个条件来优雅地关闭所有线程。

    // 无限等待(不推荐)
     while (1) sleep(1);

    // 正确的方式是使用某种机制来通知主线程可以安全地关闭套接字和退出程序。

    // 由于示例的简化性质,这里我们不会实现这样的机制。

    // 注意:在实际应用中,不要忘记在程序退出前清理资源,包括取消线程和关闭套接字。

    // 示例代码结束,这里不会真正退出程序。

    // 清理代码(在实际应用中需要实现):
    // pthread_cancel(sender_thread);
    // pthread_cancel(receiver_thread);
    // pthread_join(sender_thread, NULL);
    // pthread_join(receiver_thread, NULL);
    // close(sockfd);

    return 0; // 这行代码在实际应用中不会被执行,因为上面有一个无限循环。
}

编译它:

gcc multcast.c -o multcast -lpthread

运行结果:

【CAN 通讯】Linux Socket CAN 的应用指南 在本章中,我们将介绍 Socket CAN 的背景和重要性,以及它在现代工业和网络通讯中的应用。我们将从技术的普及和实用性出发,探讨其对用户心理和需求的适应性,以确保读者能够全面了解 Socket CAN 的核心概念和基础应用。 阅读详情

相关推荐

全志 T527_Android13 编译 [ 避坑必看 ]

Swap 概念: Linux中Swap(即:交换分区),类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行。当输入编译命令make -j16 的时候,会有如下提示,这是官方建议通过减少编译线程来解决编译时消耗内存过大的问题。Android 13 系统的编译流程,编译一共分为两部分:内核编译与 Android 编译。

公众号:嵌入式分享 2110

组播结构体ip_mreq的定义和代码的使用

//结构体的定义 struct ip_mreq { struct in_addr imr_multiaddr; //多播组的IP地址 struct in_addr imr_interface; //加入的客服端主机IP地址 } 代码的使用 //加入组播组 ip_mreq multiCast; multiCast.imr_interface.S_un.S_addr=INADDR_ANY; ...

知行合一 1万+

ArduSub深度调参指南:如何让水下机器人像鱼一样稳定游动

本文深入探讨了ArduSub水下机器人的深度调参策略,旨在解决ROV在水下晃动、响应迟钝等问题。文章系统解析了级联PID控制逻辑,并针对静水与水流环境,提供了具体的深度保持与姿态控制调参方法、实战日志分析技巧以及异常振荡处理方案,帮助用户实现水下机器人稳定、流畅的游动性能。

CAT789的专栏 371

Linux网络编程之扩展-下

1 广播 1.1 广播相关概念 一、单播   前面介绍的数据包发送方式只有一个接受方,称为单播。 二、广播   同时发给局域网中的所有主机,称为广播。只有用户数据报(使用UDP协议)套接字才能广播。 三、广播地址 1、以192.168.1.0 (255.255.255.0) 网段为例,最大的主机地址192.168.1.255代表该网段的广播地址。 2、发到该地址的数据包被所有的主机接收。 3、25...

y_q_m的博客 747

【NVIDIA驱动的顽固问题】---- /dev/sdax:clean,xxx/xxx files,xxx/xxx blocks ---- 最全解决方法

本文的意义在于整理总结关于此问题的全部解决方法,希望能给大家节约时间。

lc1852109的博客 3122

SAP DRC 是什么?一文读懂 SAP Document and Reporting Compliance 的定位、架构与落地案例

把视线拉长,会发现SAP DRC的价值并不仅是用来交差的工具。它更像是企业在全球化经营中建设的一套公共底座:既能以最低的重复成本去应对各国不断演进的监管要求,也能为财务数字化与供应链协同提供可信数据回路。依托本地与云的分层职责、与的生态联动、以及按国家不断更新的任务目录,企业可以将合规变成一种标准化、工程化、可持续运营的能力。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1646

Linux网络编程 - 多播与广播

本篇博文主要讲解多播与广播的基本概念以及基于多播与广播的网络编程实现方法。

yunfan 2414

基于SiamFC的红外目标跟踪

初始化阶段:在第一帧中,通过用户标注获得目标框,从目标区域中提取一个固定大小的模板(称为 exemplar)。搜索阶段:在后续帧中,在以当前目标中心为中心的较大区域(称为 instance)内进行搜索,将模板与搜索区域通过卷积操作得到响应图。位置更新:在响应图中找到峰值位置,并转换到原图坐标,用以更新目标中心。部分实现中还会考虑多尺度搜索和目标尺寸更新。import cv2# 定义 SiamFC 简易网络(示例)# 特征提取部分,注意红外图像通常为单通道,使用较少的卷积核数提高实时性。

weixin_43745234的博客 774

socket之UDP组播(多播)

1. 概述 1.1 单播用于两个主机间单对单的通信 1.2广播用于一个主机对整个局域网上所有主机上的数据通信 1.3单播和广播是两个极端,要么对一个主机进行通信,要么对整个局域网的主机进行通信 1.4实际情况下,经常需要对一组特定的主机进行通信,而不是所有局域网上的主机,这时候就有了组播 1.5IP组播(也称多址广播或多播),是一种允许一台或多台主机发送数据包到多台主机的TCP/IP网路技术。 1.6多播是 IPv6 数据包的 3 种基本目的地址类型之一,多播是一点对多点的通信, IPv6 没有采用 IPv

weixin_44522306的博客 2万+

【OpenClaw企业级智能体实战】第09篇:OpenClaw金融投研实战:17个场景+完整代码,打造专属数字研究员

金融投研面临信息过载、流程重复、数据安全合规三大核心痛点,OpenClaw作为本地部署的新一代AI智能体,凭借“长期记忆+主动执行+数据不出域”的优势,成为券商分析师集体追捧的效率工具。本文基于8家头部券商公开研报,拆解OpenClaw在金融投研的17个核心应用场景(信息处理、研报撰写、量化策略、流程自动化),详解原理、技术选型、实操流程,并提供可直接运行的完整代码与执行结果。文章兼顾新手入门与进阶提升,强调安全隔离部署与幻觉防范,读者可按步骤搭建专属投研智能体,将信息处理、数据整理等重复工作效率提升80%

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 672

python实现带符号的二进制数转换十进制数 (附完整源码)

python实现带符号的二进制数转换十进制数 (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 553

后台核心编程(十二):网络编程-多播与广播

1 多播 多播(Multicast)⽅式的数据传输是基于 UDP 完成的。因此 ,与 UDP 服务器端/客⼾端的实现⽅式⾮常接近。区别在于,UDP 数据传输以单⼀⽬标进⾏,而多播数据同时传递到加⼊(注册)特定组的⼤量主机。换⾔之,采⽤多播⽅式时,可以同时向多个主机传递数据。 1.1 多播的数据传输方式以及流量方面的优点 多播的数据传输特点可整理如下: 多播服务器端针对特定多播组,只发送 1 次数...

月光骆驼的博客 376

Kubernetes(K8s)从入门到精通系列之一:一篇文章了解K8s全部核心知识点

Kubernetes(K8s)从入门到精通系列之一:一篇文章了解K8s全部核心知识点

zhengzaifeidelushang的博客 849

linux组播自发自收 qt,Qt那些事0.0.27 之 QUdpSocket组播通讯

刚刚写的因为网断了就丢了,不想写了。关于组播通信失败,大概率因为多网卡,通过ipconfig可以查看具体网卡情况。C:\WINDOWS\system32>ipconfig无线局域网适配器 WLAN:连接特定的 DNS 后缀 . . . . . . . :本地链接 IPv6 地址. . . . . . . . : fe80::--------78%18IPv4 地址 . . . . . . ....

weixin_31642531的博客 788

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

linux组播通讯

/************linux 组播发送端**********/ #include #include           /* See NOTES */ #include #include #include #include int main(void) {   int sockfd;   struct sockaddr_in baddr;   int add

linuxarmsummary的专栏 808

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Linux 多播(组播)例程

本例程修改自:http://zhoulifa.bokee.com/6066993.html 博文提供的例程。 ser.c  #include #include #include #include #include #include string.h> #include #include #define BUFLEN 255 int main

nickol51的专栏 1012

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

linux组播测试脚本,Linux网络编程组播测试代码

#include #include #include #include #include #include #include #include #define BUFLEN 255int main(int argc, char **argv){struct sockaddr_in peeraddr;struct in_addr ia;int sockfd;char recmsg[BUFLEN + ...

weixin_39715460的博客 304

linux 组播编程

组播客户端代码如下:<br /><br /><br /> #include <sys/types.h><br /> #include <sys/socket.h><br /> #include <arpa/inet.h><br /> #include <stdio.h><br /> #include <stdlib.h><br /> #include <string.h><br /><br /> #define BUFLEN 255<br /> int main(int argc, char

3768

Linux socket 组播示例

最近一直在做linux的网络,现在作个总结,陆续贴出来。在网上搜了很多资料 ,其中周立发的博客对我的学习参考作用最大,谢谢前辈。直接上代码吧,一个很简单udp 组播通信的例子,分别为服务器端和客户端的代码。1、服务器端代码 (multi_udp_server.c)#include<sys/types.h> #include<sys/socket.h&gt...

weixin_33853794的博客 550

Linux网络编程 之 UDP 组播

最近一直在做linux的网络,现在作个总结,陆续贴出来。 在网上搜了很多资料 ,其中周立发的博客对我的学习参考作用最大,谢谢前辈。 直接上代码吧,一个很简单udp 组播通信的例子,分别为服务器端和客户端的代码。 1、服务器端代码 (multi_udp_server.c) #include #include #include #include #inc

6271

socket之UDP通讯

该文章简单的讲解linux中socket UDP通讯 UDP(user datagram protocol)的中文叫用户数据报协议,属于传输层。UDP是面向非连接的协议,它不与对方建立连接,而是直接把我要发的数据报发给对方。所以UDP适用于一次传输数据量很少、对可靠性要求不高的或对实时性要求高的应用场景。正因为UDP无需建立类如三次握手的连接,而使得通信效率很高。 1.UDP通讯模型 服务端:socket(创建套接字)–>bind(绑定套接字)–>recvfrom/sendto(对客服端进行读写

weixin_44522306的博客 1万+

Linux网络编程 之 UDP 组播实例

一个很简单udp 组播通信的例子,分别为服务器端和客户端的代码。 1、服务器端代码 (multi_udp_server.c) [objc] view plaincopy #include    #include    #include    #include    #include    #include

sin0803的专栏 2997

Linux网络编程组播测试代码

Linux网络编程组播测试代码(转载) 组播客户端代码如下: #include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <stdio.h>#include <stdlib.h>#include <s...

a9j77749的博客 201

Linux C++ UDP Socket(超详细)

​ 使用UDP协议进行信息的传输之前不需要建议连接。换句话说就是客户端向服务器发送信息,客户端只需要给出服务器的ip地址和端口号,然后将信息封装到一个待发送的报文中并且发送出去。至于服务器端是否存在,或者能否收到该报文,客户端根本不用管。 ​ 通常用于实时性较高,数据量较大,丢一两帧影响不大的情况。如视频聊天 电话聊天 传感器广播消息 汽车发送位置信息等 。 环境:Linux 语言:C++ 通讯方式:UDP 1. udp 通讯的流程 下图是一个UDP通讯的时序图:实现客户端发消息到服务器端。 #me

休息一下接着来的博客 1万+
上一篇: 第九篇:Linux下socket广播通讯的实现
下一篇: 第三篇:TCP/IP杂记
wh_xia_jun
博客等级 码龄16年 1335粉丝 405原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值