当前位置: 首页 > news >正文

嵌入式学习记录5.18(多点通信)

一、套接字属性设置相关函数

       #include <sys/types.h>          /* See NOTES */#include <sys/socket.h>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);功能:获取或设置套接字相关层中的相关属性的值参数1:套接字文件描述符参数2:网络层次:应用层:SOL_SOCKET (man 7 socket)传输层(TCP):IPPROTO_TCP (man 7 tcp)传输层(UDP):IPPROTO_UDP (man 7 udp)网络层:IPPROTO_IP (man 7 ip)参数3:当前层要设置或获取的属性名称,每层常设置的名称如下表所示:参数4:要给参数3属性设置的值参数5:参数4的大小返回值:成功返回0,失败返回-1并置位错误码

#include<myhead.h>int main(int argc, const char *argv[])
{//创建套接字int fd = socket(AF_INET, SOCK_DGRAM, 0);if(fd == -1){perror("socket errorr");return -1;}//想要知道当前套接字能否进行端口号和地址的快速重用int reuse = -1;int optlen = sizeof(reuse);if(getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, &optlen) ==-1){perror("getsockopt error");return -1;}printf("reuse = %d\n", reuse);        // 0,表示套接字默认不允许端口号快重用//设置端口号快速重用int optval = 1;if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1){perror("setsockopt error");return -1;}//再次获取套接字属性的值reuse = -1;if(getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, &optlen) ==-1){perror("getsockopt error");return -1;}printf("reuse = %d\n", reuse);        // 1,表示已经设置端口号快速重用了return 0;
}

二、单播

就是实现一对一的通信,我们之前所学的TCP或UDP通信方式都是使用的是单播

发送端和接收端是确定的

三、多点通信

1> 实现主机之间的一对多的通信,一个发送端可以对应多个接收端

2> 对于接收端而言,无论愿不愿意接收,都会收到消息

3> 只能基于UDP实现多点通信

4> 实现多点通信的方式:广播、组播

3.1 广播

1> 能够实现主机的一对多的通信

2> 在当前网络下的所有主机都能接收到广播消息

3> 对于广播的发送端套接字而言,需要将其设置成允许广播的状态

4> 广播地址:网络号 + 255

5> 广播消息不允许穿过路由器

6> 广播分为发送端和接收端

7> 广播的发送端流程----> 类似于UDP的客户端

1、socket:创建用于通信的套接字文件描述符
2、setsockopt:设置当前套接字允许广播, level:SOL_SOCKET      optname:SO_BROADCAST     optval: int
3、bind:可绑定也可以不绑定
4、发送广播消息:sendto目的IP地址:广播地址目的Port:与接收端保持一致
5、close:关闭套接字
#include<myhead.h>
#define IP "192.168.125.255"          //广播地址
#define PORT 6789                    //端口号int main(int argc, const char *argv[])
{//1、创建套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd == -1){perror("socket error");return -1;}//2、设置套接字允许广播int broadcast = 1;if(setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) == -1){perror("setsockopt error");return -1;}//3、发送消息//3.1 填充对端地址信息结构体struct sockaddr_in rin;rin.sin_family = AF_INET;rin.sin_port = htons(PORT);rin.sin_addr.s_addr = inet_addr(IP);char sbuf[128] = "";while(1){//从终端获取数据printf("请输入>>>");fgets(sbuf, sizeof(sbuf), stdin);sbuf[strlen(sbuf)-1] = 0;//将数据广播出去sendto(sfd, sbuf, strlen(sbuf), 0, (struct sockaddr*)&rin, sizeof(rin));printf("发送成功\n");}//4、关闭套接字close(sfd);return 0;
}

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

1、socket:创建用于通信的套接字文件描述符 2、bind:必须绑定 IP地址:广播地址 Port:与发送端保持一致 3、recvfrom:接收广播消息 4、close:关闭套接字

#include<myhead.h>
#define IP "192.168.125.255"          //广播地址
#define PORT 6789                    //端口号int main(int argc, const char *argv[])
{//1、创建套接字int rfd = socket(AF_INET, SOCK_DGRAM, 0);if(rfd == -1){perror("socket error");return -1;}//2、绑定ip和端口号//2.1 填充地址信息结构体struct sockaddr_in rin;rin.sin_family = AF_INET;rin.sin_port = htons(PORT);rin.sin_addr.s_addr = inet_addr(IP);//2.2 绑定if(bind(rfd, (struct sockaddr*)&rin, sizeof(rin)) == -1){perror("bind error");return -1;}//3、接受消息char rbuf[128] = "";while(1){bzero(rbuf, sizeof(rbuf));         //清空容器//读取数据recvfrom(rfd, rbuf, sizeof(rbuf), 0, NULL, NULL);//recv(rfd, rbuf, sizeof(rbuf), 0);printf("收到广播消息:%s\n", rbuf);}//4、关闭套接字close(rfd);return 0;
}

3.2 组播

1> 组播也是实现一对多的通信

2> 组播地址:D类网络---> [224.0.0.0 -- 239.255.255.255]

3> 组播也分为发送端和接收端,对于接收端而言,要加入多播组后,才能收到组播消息

4> 组播的发送端 ----> 类似于UDP的客户端

1、socket:创建用于通信的套接字文件描述符
2、bind:可绑定也可以不绑定
3、发送广播消息:sendto目的IP地址:组播地址目的Port:与接收端保持一致
4、close:关闭套接字
#include<myhead.h>int main(int argc, const char *argv[])
{//1、创建套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd == -1){perror("socket error");return -1;}//3、发送消息//3.1 填充对端地址信息结构体struct sockaddr_in rin;rin.sin_family = AF_INET;rin.sin_port = htons(5555);rin.sin_addr.s_addr = inet_addr("224.1.1.1");  //组播地址char sbuf[128] = "";while(1){//从终端获取数据printf("请输入>>>");fgets(sbuf, sizeof(sbuf), stdin);sbuf[strlen(sbuf)-1] = 0;//将数据广播出去sendto(sfd, sbuf, strlen(sbuf), 0, (struct sockaddr*)&rin, sizeof(rin));printf("发送成功\n");}//4、关闭套接字close(sfd);return 0;
}

5> 组播的接收端 ----> 类似于UDP的服务器端

1、socket:创建用于通信的套接字文件描述符
2、setsockopt:将当前套接字加入多播组, level:IPPROTO_IP    optname:IP_ADD_MEMBERSHIP    optval:struct ip_mreqstruct ip_mreqn {struct in_addr imr_multiaddr;    //广播地址struct in_addr imr_address;      //主机ipint            imr_ifindex;      //网卡编号   可以通过指令 ip ad 进行查看当前网卡设备的编号};3、bind:必须绑定IP地址:广播地址Port:与发送端保持一致
4、recvfrom:接收广播消息
5、close:关闭套接字
#include<myhead.h>int main(int argc, const char *argv[])
{//1、创建套接字int rfd = socket(AF_INET, SOCK_DGRAM, 0);if(rfd == -1){perror("socket error");return -1;}//2、加入多播组//2.1 创建结构体变量struct ip_mreqn imq;imq.imr_multiaddr.s_addr = inet_addr("224.1.1.1");    //广播地址imq.imr_address.s_addr = inet_addr("192.168.125.221");  //主机IPimq.imr_ifindex = 2;            //网卡索引//2.2 设置套接字if(setsockopt(rfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imq, sizeof(imq)) == -1){perror("setsockopt error");return -1;}printf("加入多播组成功\n");//3、绑定//3.1 填充地址信息结构体struct sockaddr_in rin;rin.sin_family = AF_INET;rin.sin_port = htons(5555);         //端口号rin.sin_addr.s_addr = inet_addr("224.1.1.1");   //组播IP// 3.3绑定if(bind(rfd, (struct sockaddr*)&rin, sizeof(rin)) == -1){perror("bind  error");return -1;}//4、接受消息char rbuf[128] = "";while(1){bzero(rbuf, sizeof(rbuf));         //清空容器//读取数据recvfrom(rfd, rbuf, sizeof(rbuf), 0, NULL, NULL);//recv(rfd, rbuf, sizeof(rbuf), 0);printf("收到组播消息:%s\n", rbuf);}//5、关闭套接字close(rfd);return 0;
}

相关文章:

  • Node.js和npm常用命令
  • element-ui组件table去除下方滚动条,实现鼠标左右拖拽移动表格
  • 四、通信和网络安全—局域网|广域网|远程连接和攻击技术(CISSP)
  • 让大模型更聪明——复杂而艰巨的任务
  • C++类与对象的特性
  • 【算法刷题day60】Leetcode:84. 柱状图中最大的矩形
  • 大规模语言模型的书籍分享
  • 听说部门来了个00后测试开发,一顿操作给我整麻了
  • 自己动手写docker——Namespace
  • 【chagpt】广泛使用API之前:考虑成本和数据隐私
  • 01-05.Vue自定义过滤器
  • 在树莓派3B+中下载opencv(遇到的各种问题及解决)
  • 宿舍管理系统代码详解(操作界面)
  • 人人皆是黑客?EvilProxy推出一键反向代理服务
  • vue深度选择器(:deep​)
  • Docker下部署自己的LNMP工作环境
  • Effective Java 笔记(一)
  • iOS小技巧之UIImagePickerController实现头像选择
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Java反射-动态类加载和重新加载
  • MD5加密原理解析及OC版原理实现
  • Promise面试题,控制异步流程
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • spring学习第二天
  • 阿里云Kubernetes容器服务上体验Knative
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 网页视频流m3u8/ts视频下载
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #Java第九次作业--输入输出流和文件操作
  • #每日一题合集#牛客JZ23-JZ33
  • (02)Unity使用在线AI大模型(调用Python)
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (八)c52学习之旅-中断实验
  • (六)激光线扫描-三维重建
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (转)shell调试方法
  • *2 echo、printf、mkdir命令的应用
  • 、写入Shellcode到注册表上线
  • .Net Core 生成管理员权限的应用程序
  • .NET Core中Emit的使用
  • .NET WebClient 类下载部分文件会错误?可能是解压缩的锅
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • .NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.
  • .NET上SQLite的连接
  • ?.的用法
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [ linux ] linux 命令英文全称及解释
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——
  • [ABP实战开源项目]---ABP实时服务-通知系统.发布模式
  • [BZOJ4554][TJOI2016HEOI2016]游戏(匈牙利)