嵌入式学习——3——多点通信

news2024/11/19 7:42:22

1、套接字选项(socket options)

int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

功能:获取或设置套接字在不同层级上的相关属性

参数:

sockfd:  要获取或设置的套接字文件描述符

level:     表示要获取或设置的层

                        应用层        SOL_SOCKET

                        传输层        IPPROTO_TCP  IPPROTO_UDP

                        网络层        IPPROTO_IP

optname:当前层的数下名称见下表

optval:     要获取或设置的属性值的起始地址

optlen:     optval的大小

返回值:成功 0   失败 -1  并重置错误码

快速重用地址

int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1) {
      perror("setsockopt error");
      return -1;
}

2、单播

1、主机之间存在的是一对一的通信方式,交换机以及路由器对数据只进行转发,不进行复制

2、每次只有两个实体之间进行相互通信,发送端和接收端都是唯一确定的

3、广播和组播的区别

组播是一种多对多的通信方式,其中消息被发送到一个特定的组播地址,只有加入该组播地址的主机才能接收到这个消息。组播允许发送方只向特定的一组接收方发送消息,可以在节省带宽的同时实现多对多通信,广泛应用于IP电话、视频会议、多媒体流等场景。


广播是一种发送消息给所有主机的通信方式。在广播中,消息被发送到一个广播地址,该地址会被所有网络中的主机接收。广播是一种无条件的发送方式,因此它常常被用于网络中一些需要向所有主机广播消息的场景,例如DHCP自动分配IP地址和ARP协议中解析MAC地址等。
总结:组播和广播的主要区别在于它们【发送消息的方式】和目【标接收者的范围不同】。广播是一种无条件的发送方式,消息被发送到所有主机;而组播则是有条件的发送方式,消息只会被发送到加入该组播地址的特定主机。

4、广播

1、广播是允许通信实体之间完成一对多的通信方式,网络对其中每一台发送数据的主机信息都进行无条件的复制后并转发给其他所有主机

2、所有的主机都会收到广播消息(不管是否愿意接收)

3、广播只能由UDP通信方式来实现

4、广播消息,只能在当前网络中进行传播,不允许传过路由器

5、广播地址:网络号 + 255

6、广播分为发送端和接收端实现

        3.1 广播的发送端------->类似于UDP的客户端

socket          创建用于通信的套接字文件描述符

setsockopt (SOL_SOCKET   SOBROADCAST )           设置该套接字允许发送广播消息

bind         绑定IP地址和端口号(可选)

sendto          向广播地址发送数据

        广播地址IP:网络号 + 255

        端口号:与接收端保持一致

close          关闭套接字

int main(){
    //1、创建用于通信的套接字文件描述符:socket
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }

    //2、设置该套接字允许发送广播消息:setsockopt     ---> SOL_SOCKET 
    //---> SO_BROADCAST
    int broadcast = 1;
    if(setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) ==-1)
    {
        perror("setsockopt error");
        return -1;
    }

    //3、绑定IP地址和端口号(可选)
    //4、向广播地址发送数据:sendto

    // 广播地址IP:网络号 + 255
    // 端口号:与接收端保持一致
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    rin.sin_port = htons(6666);     //跟接收端保持一致
    rin.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.255");


    //发送数据
    char wbuf[128] = "";
    while(1) {
       //从终端获取数据
       fgets(wbuf, sizeof(wbuf), stdin);
       wbuf[strlen(wbuf)-1] = 0;

       //发送给广播消息
       sendto(sfd, wbuf, strlen(wbuf), 0, (struct sockaddr*)&rin, sizeof(rin));
       printf("发送成功\n");

       //判断发送的消息
       if(strcmp(wbuf, "over") == 0)
       {
           break;
       }
    }

    //5、关闭套接字:close
    close(sfd);
    return 0;

}

        3.2 广播的接收端------->类似于UDP的服务器端

1、创建用于通信的套接字文件描述符

2、填充地址信息结构体:

        ip:广播地址

        port:与发送端保持一致

3、绑定端口号和IP地址(必须)

4、接受发送端发来的消息:recvfrom

5、关闭套接字:close

int main(){
    //1、创建用于通信的套接字文件描述符
    int rfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(rfd == -1) {
        perror("socket error");
        return -1;
    }

    //2、填充地址信息结构体:
    //ip:广播地址
    //port:与发送端保持一致
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    rin.sin_port = htons(6666);     //端口号
    rin.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.255"); //广播ip地址
    
    //3、绑定端口号和IP地址(必须)
    if(bind(rfd, (struct sockaddr*)&rin, sizeof(rin)) == -1) {
        perror("bind error");
        return -1;
    }
    //4、接受发送端发来的消息:recvfrom
    char rbuf[128] = "";
    while(1)
    {
        //清空容器
        bzero(rbuf, sizeof(rbuf));
        //读取数据
        recv(rfd, rbuf, sizeof(rbuf), 0);
        //展示
        printf("收到广播消息:%s\n", rbuf);

        //判断广播是否结束
        if(strcmp(rbuf, "over") == 0) {
            break;
        }
    }

    //5、关闭套接字:close
    close(rfd);
    return 0;
}

5、组播

1、由于广播通信过程中,会占用大量的网络带宽,影响正常通信,如果通信的主机较少的话,可以引入组播

2、组播也是实现主机之间一对多的通信方式

3、要求所有接受端主机加入多播组,只有加入多播组的主机才能收到消息

4、对于发送端而言,只需向该多播组中发送消息即可,无需其他设置

5、组播也是使用UDP实现的

6、组播地址:D类网络 【224.0.0.0 --- 239.255.255.255】

7、组播也分为发送端和接收端

        4.1 组播的发送端  ---> 类似于UDP的客户端流程

1、创建用于通信的套接字文件描述符:socket

2、绑定IP地址和端口号(可选)

3、向组播地址发送数据:sendto

        广播地址IP:【224.0.0.0 --- 239.255.255.255】

        端口号:与接收端保持一致

4、关闭套接字:close

int main()
{
    //1、创建用于通信的套接字文件描述符:socket
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }

    //2、绑定IP地址和端口号(可选)
    //3、向组播地址发送数据:sendto
    //广播地址IP:【224.0.0.0 --- 239.255.255.255】
    //端口号:与接收端保持一致
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    rin.sin_port = htons(5555);
    rin.sin_addr.s_addr = inet_addr("224.1.2.3");

    //数据的发送
   //发送数据
   char wbuf[128] = "";
   while(1)
   {
       //从终端获取数据
       fgets(wbuf, sizeof(wbuf), stdin);
       wbuf[strlen(wbuf)-1] = 0;

       //发送给广播消息
       sendto(sfd, wbuf, strlen(wbuf), 0, (struct sockaddr*)&rin, sizeof(rin));
       printf("发送成功\n");

       //判断发送的消息
       if(strcmp(wbuf, "over") == 0)
       {
           break;
       }
   }


    //5、关闭套接字:close
    close(sfd);

    return 0;
}

        4.2 组播的接收端流程 ---> 类似于UDP的服务器端流程

1、创建用于通信的套接字文件描述符:socket

2、将该套接字加入多播组:

        setsockopt ---> IPPROTO_IP --> IP_ADD_MEMBERSHIP

属性类型:

        #include <netinet/in.h>

        struct ip_mreqn {

                struct in_addr imr_multiaddr; /* 组播地址 */

                struct in_addr imr_address; /* 主机ip地址 */

                int imr_ifindex; /* 设备索引,可以通过 ip ad指令查看, 也可以填0,表示使用

                                        默认的索引*/ };

3、填充地址信息结构体:

        ip:组播地址

        port:与发送端保持一致

4、绑定端口号和IP地址(必须)

5、接受发送端发来的消息:recvfrom

6、关闭套接字:close

int main() {
    //1、创建用于通信的套接字文件描述符:socket
    int rfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(rfd == -1) {
        perror("socket error");
        return -1;
    }

    //2、将该套接字加入多播组:setsockopt   --->  IPPROTO_IP    --> IP_ADD_MEMBERSHIP 
    struct ip_mreqn  imr;
    imr.imr_multiaddr.s_addr = inet_addr("224.1.2.3");
    imr.imr_address.s_addr = inet_addr("xxx.xxx.xxx.xxx");//本机主机ip地址
    imr.imr_ifindex = 2;

    //设置套接字选项,加入多播组
    if(setsockopt(rfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr))==-1) {
        perror("setsockopt error");
        return -1;
    }

    //3、填充地址信息结构体:
    //ip:组播地址
    //port:与发送端保持一致
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    rin.sin_addr.s_addr = inet_addr("224.1.2.3");
    rin.sin_port = htons(5555);

    //4、绑定端口号和IP地址(必须)
    if(bind(rfd, (struct sockaddr*)&rin, sizeof(rin)) == -1) {
        perror("bind error");
        return -1;
    }

    //5、接受发送端发来的消息:recvfrom
    char rbuf[128] = "";
    while(1) {
        //清空容器
        bzero(rbuf, sizeof(rbuf));

        //读取数据
        recv(rfd, rbuf, sizeof(rbuf), 0);

        //展示
        printf("收到广播消息:%s\n", rbuf);
        //判断广播是否结束

        if(strcmp(rbuf, "over") == 0) {
            break;
        }
    }

    //6、关闭套接字:close
    close(rfd);
    return 0;
}

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

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

相关文章

二叉树——基础知识详解

前言&#xff1a; 经过前面的学习&#xff0c;我们接下来要开始二叉树的学习&#xff0c;因二叉树有难度&#xff0c;为了方便讲解以及各位的理解&#xff0c;本节知识会分成不同的小节进行学习&#xff0c;在本阶段只学习初阶的二叉树&#xff08;堆&#xff0c;二叉数基本知识…

多分支拓扑阻抗匹配

最近测试信号质量&#xff0c;发现在有过冲、振铃等问题的时候大部分硬件工程师喜欢直接调大匹配电阻或者减小驱动电流&#xff0c;虽然这种操作是有效果的&#xff0c;但是我认为应该还可以更严谨的计算下&#xff0c;而不是选几个电阻多次尝试&#xff0c;显得不是很专业。 …

SOLIDWORKS正版一年多少钱 2024版报价

SOLIDWORKS软件作为一款优秀的三维设计工具&#xff0c;以其强大的功能和优质的设计工具&#xff0c;为设计师们提供了前所未有的便利。SOLIDWORKS三维设计软件是一款多科学集成软件&#xff0c;它在产品开发和制造方面发挥着重要作用。 作为整个SOLIDWORKS产品开发解决方案套件…

boost asio异步服务器(2)实现伪闭包延长连接生命周期

闭包 在函数内部实现一个子函数&#xff0c;子函数的作用域内能访问外部函数的局部变量。闭包就是能够读取其他函数内部变量。但是由于闭包会使得函数中的变量都被保存在内存中&#xff0c;内存消耗很大&#xff0c;所以不能滥用闭包&#xff0c;否则会造成程的性能问题&#x…

Discourse 使用 DiscourseConnect 来进行用户数据同步

我们都知道 Discourse 的用户管理和设置都高度依赖电子邮件。 如果 Discourse 没有设置电子邮件 SMTP 的话&#xff0c;作为管理员是没有办法对用户邮箱进行修改并且通过验证的。 可以采取的办法是通过 Discourse 的 DiscourseConnect 来进行用户同步。 根据官方的说法&…

Golang原生http实现中间件

Golang原生http实现中间件 中间件&#xff08;middleware&#xff09;&#xff1a;常被用来做认证校验、审计等 大家常用的Iris、Gin等web框架&#xff0c;都包含了中间件逻辑。但有时我们引入该框架显得较为繁重&#xff0c;本文将介绍通过golang原生http来实现中间件操作。全…

vue复习选择题2

1. 下面哪一个方法可以实现判断元素的class属性是否含有pp样式&#xff1f; &#xff08;A&#xff09; A. hasClass(“pp”)B. is(“pp”)C. attr(“class”,“pp”)D. toggleClass(“pp”) [!NOTE] 当涉及到在 jQuery 中判断元素的类属性时&#xff0c;下面是各个选项的作用…

2024/5/28 P1247 取火柴游戏

取火柴游戏 题目描述 输入 k k k 及 k k k 个整数 n 1 , n 2 , ⋯ , n k n_1,n_2,\cdots,n_k n1​,n2​,⋯,nk​&#xff0c;表示有 k k k 堆火柴棒&#xff0c;第 i i i 堆火柴棒的根数为 n i n_i ni​&#xff1b;接着便是你和计算机取火柴棒的对弈游戏。取的规则如下&…

AI批量剪辑视频素材,高效混剪快速出片/矩阵发布,一键管理自媒体账号。

今天给大家分享一个超级好用的办公神器。特别是玩矩阵的企业&#xff0c;这款工具高效解决短视频剪辑问题。 这款软件可以帮你快速生产出1000条视频内容,而且还能把内容同步到多个平台账号上&#xff0c;多平台矩阵发布。 这款系统真的太棒了! 不仅操作简单,而且功能超强大。 …

干冰清洗机的清洗原理及应用

干冰清洗机的清洗原理及应用可以详细阐述如下&#xff1a; 一、清洗原理 干冰清洗机的清洗原理主要基于干冰的低温冷冻作用。干冰在常温下会迅速升华&#xff0c;吸收大量的热量&#xff0c;使周围的温度迅速降低。当干冰颗粒通过特殊的干冰清洗机喷射到清洗物体表面时&#…

Python | Leetcode Python题解之第104题二叉树的最大深度

题目&#xff1a; 题解&#xff1a; class Solution:def maxDepth(self, root: TreeNode) -> int:if not root: return 0queue, res [root], 0while queue:tmp []for node in queue:if node.left: tmp.append(node.left)if node.right: tmp.append(node.right)queue tmp…

素数判断的奥秘与编程实践

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、素数定义的深入理解 二、非素数的例子与思考 三、素数判断的编程实现 1. 穷举法判断素…

多语言印度红绿灯系统源码带三级分销代理功能

前端为2套UI&#xff0c;一套是html写的&#xff0c;一套是编译后的前端 后台功能很完善&#xff0c;带预设、首充返佣、三级分销机制、代理功能。 东西很简单&#xff0c;首页就是红绿灯的下注页面&#xff0c;玩法虽然单一&#xff0c;好在不残缺可以正常跑。

SD Flash介绍

作为一家专业生产存储芯片及存储卡的原厂&#xff0c;我们时常收到客户关于SD Flash的各种技术问题。MK米客方德将详细解答关于SD Flash的常见问题&#xff0c;助您更好地了解这一重要存储技术。 SD Flash是一种常见的存储卡技术&#xff0c;广泛应用于各种便携式设备中&#x…

无人机+EasyDSS互联网视频平台:构建秸秆焚烧监控的“天眼”系统

一、方案背景 在每年的夏收时节&#xff0c;秸秆禁烧成为各地政府面临的一项重要任务。随着夏收季节的结束&#xff0c;大量农作物秸秆的处理问题逐渐凸显。一方面农作物种植面积辽阔&#xff0c;禁烧区域面积较大&#xff0c;监管巡逻人员的数量有限&#xff0c;无法全面顾及…

微软提出“Copilot+ PCs”构想,强调本地AI处理;OpenAI暂停ChatGPT语音功能因声音相似争议

&#x1f989; AI新闻 &#x1f680; 微软提出“Copilot PCs”构想&#xff0c;强调本地AI处理 摘要&#xff1a;在微软 Build 开发者前瞻大会上&#xff0c;CEO 萨蒂亚・纳德拉介绍了“Copilot PCs”&#xff0c;一种新类 Windows PC&#xff0c;需配备神经处理单元&#xf…

centos7单机安装openstack

前提&#xff1a;如果你使用 VMware 一定要打开 虚拟化&#xff0c;点设置->处理器下面有一些选项&#xff0c;一定要勾选&#xff0c;如下图所示&#xff0c;勾选后&#xff0c;启动系统后使用lscpu查看 virtaulization 是否正确 1.更新yum源&#xff1a; #yum update2.关闭…

2024年,史上最强的数据库资料集合

&#x1f4a8;&#x1f3f9;&#x1f300; 2024年&#xff0c;史上最强的数据库资料集合 N种数据库的全方位整理&#xff1a; mysql&#xff0c;mariaDB&#xff0c;Percona Server&#xff0c;Redis&#xff0c;RocksDB&#xff0c;Cassandra&#xff0c;CouchDB&#xff0c…

【平渊随笔】我们为什么要复盘?吸取教训,予其惩,而毖后患!

《平渊》 肆 "予其惩&#xff0c;而毖后患" "复盘" 一词源于围棋术语&#xff0c;对弈者完成一局棋后&#xff0c;重新摆局&#xff0c;审视棋局中的优势与失误&#xff0c;看哪些地方下得好&#xff0c;哪些地方下得不好&#xff0c;有没有更优解&#xf…

(四)MySQL 事务

欢迎访问 事务有哪些特性&#xff1f; 事务是由 MySQL 的引擎来实现的&#xff0c;我们常见的 InnoDB 引擎它是支持事务的。 不过并不是所有的引擎都能支持事务&#xff0c;比如 MySQL 原生的 MyISAM 引擎就不支持事务&#xff0c;也正是这样&#xff0c;所以大多数 MySQL 的…