c语言实现udp广播和组播

2023-05-16

目录

1、UDP广播通信

2、UDP组播通信

1、UDP广播通信

单播:数据包发送方式只有一个接受方

广播:同时发给局域网中的所有主机

只有用户数据报套接字(使用UDP协议)才能广播

以192.168.63.0网段为例:..***.255 代表该网段的广播地址。发送给该地址的数据包被所有主机接收

实现广播的过程(UDP协议)

 广播发送端: ----> 添加广播属性

1、建立套接字

2、设置该套接字允许进行广播(将广播属性添加进去),填充服务端的结构体

3、将数据发送到广播地址中(sendto(buf,192.168.x.x))

4、关闭

接收端(服务器): ----> 绑定所有主机(INADDR_ANY)

1、建立套接字

2、填充服务端的结构体,绑定广播地址和端口号(struct sockaddr_in serveraddr,serveraddr.sin_addr.s_addr = htonl(INADDR_ANY)))(需要设置端口复用) 3、创建结构体存放客户端IP和端口,接收数据

4、关闭

//2、将广播属性添加到套接字中 int on = 1; setsockopt(socketfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on)); ownaddr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY代表本机所有地址 常用方法

 广播的测试代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define GUANG_IP "192.168.5.255"    //---> 你所在局域网的广播地址
#define GUANG_PORT 60000

//udp广播server.c
int main(int argc,char** argv)
{
    //如果手动输入IP和地址
    // if(argc != 3)
    // {
    //     perror("./a.out IP PORT");
    //     return -1;
    // }

    int ret = 0;
    char buf[1024] = { 0 };

    //1、创建一个套接字文件描述符
    int socketfd = socket(AF_INET,SOCK_DGRAM,0);
    if(socketfd == -1)
    {
        perror("socket fail");
        return -1;
    }

    //设置端口复用
    int optval = 1;
    setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));

    //2、绑定广播IP和端口号
    struct sockaddr_in ownaddr;
    ownaddr.sin_family = AF_INET;
    //ownaddr.sin_port = htons(atoi(argv[2]));               //传参方式
    ownaddr.sin_port = htons(GUANG_PORT);                    //宏定义方式
    ownaddr.sin_addr.s_addr = htonl(INADDR_ANY);             //INADDR_ANY代表本机所有地址 常用方法
    ret = bind(socketfd,(struct sockaddr*)&ownaddr,sizeof(struct sockaddr_in));
    if(ret == -1)
    {
        perror("bind fail");
        return -1;
    }
    printf("绑定本机成功[%s][%d]\n",GUANG_IP,GUANG_PORT);

    //定义接收结构体,获取IP和端口
    struct sockaddr_in recv_addr;
    int len = sizeof(struct sockaddr_in);
    char *ip =NULL;
    int port = 0;

    //3、接收数据
    while(1)
    {
        //清空缓冲区
        bzero(buf,sizeof(buf));

        //接收数据
        ret = recvfrom(socketfd,buf,sizeof(buf),0,(struct sockaddr*)&recv_addr,&len);

        //解析发送端的ip和地址
        ip = inet_ntoa(recv_addr.sin_addr);
        port = ntohs(recv_addr.sin_port);

        printf("[%s][%d] 接收数据 buf:%s ret:%d\n",ip,port,buf,ret);

        if(strcmp(buf,"exit") == 0)
        {
            break;
        }

    }

    //4、关闭套接字
    close(socketfd);

    return 0;
}

//udp广播client.c
int main(int argc,char** argv)
{
    //如果手动输入IP和地址
    // if(argc != 3)
    // {
    //     perror("./a.out IP PORT");
    //     return -1;
    // }

    int ret = 0;
    char buf[1024] = { 0 };

    //1、创建一个套接字文件描述符
    int socketfd = socket(AF_INET,SOCK_DGRAM,0);
    if(socketfd == -1)
    {
        perror("socket fail");
        return -1;
    }

    //2、将广播属性添加到套接字中
    int on = 1;
    setsockopt(socketfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));

    //指定接收方
    struct sockaddr_in send_addr;
    send_addr.sin_family = AF_INET;
    send_addr.sin_port = htons(GUANG_PORT);
    send_addr.sin_addr.s_addr = inet_addr(GUANG_IP);
    printf("绑定本机成功[%s][%d]\n",GUANG_IP,GUANG_PORT);

    //3、发送数据
    while(1)
    {
        //清空缓冲区
        bzero(buf,sizeof(buf));

        scanf("%s",buf);

        ret = sendto(socketfd,buf,strlen(buf),0,(struct sockaddr*)&send_addr,sizeof(struct sockaddr_in));

        printf("发送数据 ret=%d\n",ret);

        if(strcmp(buf,"exit") == 0)
        {
            break;
        }

    }

    //4、关闭套接字
    close(socketfd);

    return 0;
}

2、UDP组播通信

组播是介于单播与广播之间,在一个局域网内,将某些主机添加到组中,并设置一个组地址.我们 只需要将数据发送到组播地址即可,加入到该组的所有主机都能接收到数据

组播特点

1)需要给组播设置IP地址,该IP必须是D类地址

2)只有UDP才能设置组播

3、IP地址分类 IP地址 = 网络号 + 主机号

网络号:指的是不同的网络

主机号:指的是同一个网段下用来识别不同的主机。

那也就是说,主机号所占的位数越多,在该网段下的主机 数越多

A类地址 :保留给政府机构使用

A类IP地址就由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须 是“0”

A类地址范围 1.0.0.1 - 126.255.255.254

B类地址 :分配给中等规模的公司

B类IP地址就由2字节的网络地址和2字节主机地址组成,网络地址的最高位必须 是“10”

B类地址范围 128.0.0.1 - 191.255.255.254

C类地址 :分配给任何需要的人

C类IP地址就由3字节的网络地址和1字节主机地址组成,网络地址的最高位必须 是“110” 13 C类地址范围 192.0.0.1 - 223.255.255.254 //192.168.14.2

D类地址 :用于组播

D类地址范围 224.0.0.1 - 239.255.255.254 //224.0.0.10

E类地址 :用于实验

E类地址范围 240.0.0.1 - 255.255.255.254

特殊地址:

每一个字节都为0的地址(“0.0.0.0”)对应于当前主机;

INADDR_ANY -->代表当前主机所有的地址

127.0.0.1 回环地址 --》在当前主机内部自动形成闭环的网络 --》主要用于主机内部不同的应用程序通信

如果你已经确定当前客户端 和 服务器 都是在同一台主机上运行,那么可以使用这个地址

组播通信的过程

 UDP组播发送端

1、建立套接字()

2、发送数据,往群聊(组播地址)中发送数据

3、关闭

UDP组播接收端

1、建立套接字

2.定义组播结构体

3、设置组播ip(初始化 组播结构体)

4.加入组播属性(也就是设置这个套接字 可以接收组播信息)

5、绑定IP地址和端口号

6、进群,加入群聊,将当前的IP地址设置到组播地址中

7、创建结构体存放客户端IP和端口,接收数据

8、关闭

 UDP组播的测试代码如下:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define GROUP_IP    "224.0.0.10"  //组播地址224开头
#define GROUP_PORT  60000

#define MY_IP   "192.168.5.184"

//udp组播server.c
int main()
{
    int ret = 0;

    //1.建立套接字
    int socket_fd = socket(AF_INET,SOCK_DGRAM,0);
    if(socket_fd < 0)
    {
        perror("socket fail");
        return -1;
    }

    //2.定义组播结构体
    struct ip_mreq vmreq;

    //3、设置组播ip(初始化 组播结构体)
    inet_pton(AF_INET,"224.0.0.10",&vmreq.imr_multiaddr); // 组播地址
    inet_pton(AF_INET,"192.168.5.184",&vmreq.imr_interface); // 需要添加到组的ip

    //4.加入组播属性(也就是设置这个套接字 可以接收组播信息)
    setsockopt(socket_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&vmreq,sizeof(vmreq));

    //5.绑定本机地址
    struct sockaddr_in my_addr;
    my_addr.sin_family = AF_INET;//地址族
    my_addr.sin_port = htons(GROUP_PORT);//端口号
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY代表本机所有地址 常用方法 注意
    ret = bind(socket_fd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr_in));
    if(ret < 0)
    {
        perror("bind fail");
        return -1;
    }
    printf("绑定本机成功[%s][%d]\n",GROUP_IP,GROUP_PORT);

    //6.接收数据
    char buf[1024] = {0};
    struct sockaddr_in recv_addr;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    char *ip = NULL;
    int port = 0;
    while(1)
    {
        bzero(buf,sizeof(buf));

        ret = recvfrom(socket_fd,buf,sizeof(buf),0,(struct sockaddr *)&recv_addr,&addrlen);
        
        ip = inet_ntoa(recv_addr.sin_addr);
        port = ntohs(recv_addr.sin_port);

        printf("[%s][%d]buf:%s ret:%d\n",ip,port,buf,ret);
    }

    //关闭套接字
    close(socket_fd);

    return 0;
}

//udp组播client.c
int main()
{
    int ret = 0;
    char buf[1024] = { 0 };

    //1、建立套接字
    int socket_fd = socket(AF_INET,SOCK_DGRAM,0);
    if(socket_fd < 0)
    {
        perror("socket fail");
        return -1;
    }

    //给组播地址发送数据
    struct sockaddr_in send_addr;
    send_addr.sin_family = AF_INET;//地址族
    send_addr.sin_port = htons(GROUP_PORT);//端口号
    send_addr.sin_addr.s_addr = inet_addr(GROUP_IP); //ip地址

    while(1)
    {
        //清空缓存区
        bzero(buf,sizeof(buf));
        
        scanf("%s",buf);

        ret = sendto(socket_fd,buf,strlen(buf),0,(struct sockaddr *)&send_addr,sizeof(struct sockaddr_in ));
        
        printf("发送数据 ret:%d\n",ret);

    }

    //关闭套接字
    close(socket_fd);

    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c语言实现udp广播和组播 的相关文章

  • C++中的.和::和:和->的区别

    在学习C 43 43 的过程中我们经常会用到 和 和 xff1a 和 gt xff0c 在此整理一下这些常用符号的区别 1 A B则A为对象或者结构体 xff1b 2 A gt B则A为指针 xff0c gt 是成员提取 xff0c A g
  • STM32 HAL库函数学习 UART篇

    从今天开始定时更新一下有关STM32 HAL库学习的过程 xff0c 主要是对HAL库函数的所有讲解 本章是关于uart串口的函数 1 HAL UART Init xff08 UART HandleTypeDef husart xff09
  • 常见排序算法性能分析比较(快排,希尔,堆排,归并,插入排序等)

    文章目录 1 各种排序算法实现及其特点1 1 直接插入排序1 2 希尔排序1 3 直接选择排序1 4 堆排序1 5 冒泡排序1 6 快速排序1 7 归并排序1 8 计数排序 2 排序算法复杂度及稳定性分析 1 各种排序算法实现及其特点 1
  • 将visdrone数据集转化为coco格式并在mmdetection上训练,附上转好的json文件

    visdrone是一个无人机的目标检测数据集 xff0c 在很多目标检测的论文中都能看到它的身影 标签从0到11分别为 ignored regions pedestrian people bicycle car van truck tric
  • mmdetection --tools工具简单使用1

    文章目录 demo使用单张图片测试 image demo py视屏推理 video demo py本地摄像头测试 xff1a webcam demo py 测试现有模型 test py单 GPU 测试多 GPU 测试 训练 train py
  • 网络---IP地址和端口

    1 网络分类 根据网络大小 xff1a 局域网 xff0c 城域网 xff0c 广域网 xff08 互联网 61 因特网 更大的广域网 xff09 根据网络的组网方式 xff1a 以太网 xff0c 令牌环网 2 IP地址 计算机网络 IP
  • 网络---协议(TCP/IP五层模型)

    文章目录 1 xff34 xff23 xff30 xff0f xff29 xff30 五层模型1 1 分层1 2 封装1 3 分用 协议 即一种约定 网络通信协议 xff1e 网络通信中的数据的格式约定 协议分层 xff1a 一些组织为了能
  • xml 中的 大于号,小于号

    amp lt lt 小于号 amp gt gt 大于号 amp amp amp 和 amp apos 单引号 amp quot 34 双引号
  • c++调用CSerial 库函数进行串口发送

    毕设做的东西要用到这个 请学弟帮忙收集了下 自己也做个整理 完整实验项目下载 https download csdn net download a897180673 10310065 用到的硬件 1 ch340 土豪金模块 2 arduin
  • 网络---字节序

    字节序 xff1a xff43 xff50 xff55 对内存中数据以字节为单位进行存取的顺序 主机字节序分为 xff1a 大端字节序 xff1a 低地址存高位 小端字节序 xff1a 低地址存低位 地址指内存地址 xff1b 在内存中 x
  • mmdetection ---转onnx模型,Netron可视化网络结构

    详细信息可以看官方文档 xff1a docs en tutorials pytorch2onnx md 这里把命令摘了出来 用法 span class token comment bash span python tools span cl
  • 链路层--->ETH(以太网)协议

    文章目录 ETH xff08 以太网 xff09 协议格式 xff1a ARP协议格式 链路层负责相邻设备之间的数据帧传输 xff0c 典型协议有 xff1a ETHH xff08 以太网协议 xff09 xff0c ARP协议 MTU x
  • BFS练手题目

    文章目录 1 员工的重要性2 腐烂的橘子3 N 叉树的层序遍历4 单词接龙5 最小基因变化6 打开转盘锁 广度优先搜索 xff08 BFS xff09 算法 xff0c 概念就不说啥了 xff0c 常用来求最短路径 xff0c 最少步数等
  • 回溯算法练习题

    回溯是一个常见的算法 xff0c 类似于深搜 广搜 xff0c 会穷举每一个可能 但是会有一个恢复选择的操作 算法核心框架如下 xff1a span class token keyword for span 选择 in 选择列表 xff1a
  • ACM输入输出练习--字符串分割

    ACM输入输出练习 学会即可举一反三 xff0c 主要针对字符串类型分割处理 这里利用getline 和字符串流来分割字符串并格式化输出 xff0c 思路大概如此 span class token macro property span c
  • Spark与hive集成、Hive On Spark 、使用Spark SQL进行数据查询配置流程

    本文主要是介绍在开源hadoop上使用Spark SQL进行数据查询 有关本文的各组件版本如下 xff1a 1 hadoop版本 span class token namespace root 64 hadoop01 span span c
  • 虚拟机网络配置中的几个相关文件

    1 cd etc sysconfig network scripts 目录下的 ifcfg eno 文件 2 more etc hosts 3 more etc hostname 问题记录 Vmware有三种网络连接模式 xff1a 桥接
  • DB2实现判断字符串是否只含数字

    背景 取出客户表中客户姓名字段含数字且只含数字的数据 最开始考虑的是使用正则表达式函数 xff0c 后来发现DB2没有像Oracle一样可以直接使用的正则表达式函数 xff0c 因此考虑使用其他方法 结论 使用DB2的translate函数
  • 华为ELK的几个知识点

    1 ELK是运行在FusionInsight HD平台中的 安装ELK之前必须先安装FusionInsight HD集群 2 ELK依赖FusionInsight HD中的两个组件 xff0c 分别是HDFS和Yarn 3 ELK必须部署在
  • Python 中获取字典的key列表和value列表

    coding utf 8 定义一个字典 dic 61 39 剧情 39 11 39 犯罪 39 10 39 动作 39 8 39 爱情 39 3 39 喜剧 39 2 39 冒险 39 2 39 悬疑 39 2 39 惊悚 39 2 39

随机推荐

  • su oracle 和 su - oracle的区别

    最近整oracle xff0c 发现su oracle过来sqlplus一直报命令不存在 后来发现是因为用su oracle切换的 xff0c 导致还是用的root的环境变量 xff0c 所以才会导致sqlplus命令不存在 xff0c 改
  • 关于Oracle 11g的RAC和Oracle 19c 的RAC在JDBC连接时的一些区别

    19c中新增的 v services可以查询各PDB对应的服务名 xff0c 根据此服务名去写JDBC的连接参数 而非19c中常用的v database视图显示的是CDB的库名 还有 show paramerter service name
  • ORA-31626 ORA-01658 使用impdp遇到的问题

    oracle使用impdp导库时遇到的问题 xff0c span class token punctuation span oracle span class token variable 64 qsrac2 span span class
  • linux安装oracle客户端——SQL*Loader

    背景 在安装Oracle数据库的时候 xff0c 一般是默认安装客户端的 但是有些特殊情况 xff0c 需要在应用服务器上安装客户端 xff0c 用于执行一些特殊操作 xff0c 此时需要安装oracle的客户端 xff0c 如使用sqll
  • 如何获取oracle的dmp文件中的表空间名称或Schema

    场景 在给定的dmp下 xff0c 使用impdp导入时 xff0c 报了一个错 xff0c 大致就是说schema在dmp中不存在 xff08 使用impdp导入时指定了schemas 61 XXX XXX XXX xff09 当时懒得去
  • 搭建Hadoop最少需要几个节点

    可以按服务所需的最小节点数进行规划 zookeeper服务 zookeeper服务最少需要3个节点 xff0c 且扩展时需为奇数个才行 HDFS HDFS中的NameNode需要2个节点 xff0c 主备配置 因此hadoop最小需要3个节
  • “远程“操作oracle数据泵impdp、expdp导入导出

    关键词 xff1a NFS 数据泵 impdp expdp oracle客户端 本文解决的主要问题 靠考如下场景 xff0c 你作为一个DBA xff0c 管理者测试环境的Oracle集群 正常情况下测试环境恢复生产数据都是由DBA来做 x
  • 数仓拉链表的缺点

    在选定拉链表时由于对于哪些表适合做拉链表没有一个统一的规范的认识 xff0c 因此出现了以下情况 xff1a 一个表是做的全量拉链表 xff0c 但是没有注意该表数据不是每天都有供数 即 xff0c 可能某一天源系统供给了该表 xff0c
  • oracle监听、启动等命令

    记录一些常用的查看状态和重启数据库的命令 监听 单机版一般为lsnrctl xff0c 集群一般为crsctl lsnrctl Listener Control 在数据库单机环境下使用lsnrctl命令 lsnrctl status 查看状
  • 多进程的python实现

    span class token keyword import span os span class token keyword import span time span class token comment os fork 负责创建一
  • Python三目运算符(三元运算符)用法详解

    我们从一个具体的例子切入本节内容 假设现在有两个数字 xff0c 我们希望获得其中较大的一个 xff0c 那么可以使用 if else 语句 xff0c 例如 xff1a if a gt b max 61 a else max 61 b 但
  • du -sh 和ls -lh的区别

    du sh显示的是文件占用的大小 ls lh显示的文件的实际大小 这里系统层面涉及一个Block Size的概念 xff0c 具体不深究 简而言之 xff0c 假如一个Block是4K xff0c 如果文件A的大小是1K xff0c 那么用
  • docker镜像创建、删除等相关操作

    一 docker镜像的形式 可以为一个tar包 xff0c 如 centos tar 此处为一个现成的镜像 使用方法为 1 加载镜像 span class token punctuation span root 64 hadoop01 sp
  • shell中的数组、循环等基本用法和注意事项

    shell中数组的表示 方法 xff1a array name 61 ele1 ele2 ele3 elen 举例 xff1a span class token punctuation span root 64 hadoop01 span
  • 离线安装rpm包

    离线安装rpm包 安装 repotrack 工具下载依赖包其他常用命令 安装 repotrack 工具 找一台在线的机器 xff08 虚拟机 xff09 xff0c 配置好yum源 span class token punctuation
  • 更改yum源

    Error Failed to download metadata for repo appstream Cannot prepare internal mirrorlist No URLs in mirrorlist 参考连接
  • 在docker中使用sqlplus

    1 找个带sqlplus的镜像 从docker hub上下载https hub docker com r sflyr sqlplus docker pull sflyr sqlplus 2 在k8s中运行 由于该镜像启动后没有运行的程序 x
  • C++常用库函数

    C 43 43 常用库函数 1 常用数学函数 头文件 include lt math gt 或者 include lt math h gt 函数原型 功能 返回值 int abs int x 求整数x 的绝对值 绝对值 double aco
  • 基于GEC6818的触摸屏

    1 输入子系统 连接操作系统的输入设备 xff0c 可不止一种 xff0c 也许是一个标准PS 2键盘 xff0c 也许是一个USB鼠标 xff0c 或者是一块触摸屏 xff0c 甚至是一个游戏机摇杆 xff0c Linux在处理这些纷繁各
  • c语言实现udp广播和组播

    目录 1 UDP广播通信 2 UDP组播通信 1 UDP广播通信 单播 xff1a 数据包发送方式只有一个接受方 广播 xff1a 同时发给局域网中的所有主机 只有用户数据报套接字 xff08 使用UDP协议 xff09 才能广播 以192