在上一篇文章中,我们通过直连电脑测试了CH395在组播环境中进行数据的收发,但在实际的使用场景中更多的是将CH395接入局域网环境中。因此,我们需要使用到一个协议——IGMP(Internet Group Management Protocol)。

  IGMP和ICMP一样,都是IP层的一部分。IGMP报文通过IP数据包进行传输,由20字节IP首部和8字节IGMP报文封装而成,其中IP首部的协议字段值为2来指明IGMP报文(重点,后续需要用上)。我们通过wireshark抓包可以发现电脑会不断的发送IGMP报文请求加入组播(图1示),而对比发现上一篇文章CH395的组播例程抓包中并没有发出该报文,所以CH395在路由环境中会不能正常收发组播数据。

图1 电脑端发送的IGMP报文

  那如何使用CH395发送该报文呢?这里教大家一个简单的快速使用方法。上面我们讲过IGMP报是通过IP数据报进行传输的,那我们就可以通过CH395的IP-RAW或者MAC-RAW的方式来自己封装该报文。那IGMP报文的内容该填写什么呢?电脑会发出组播请求报文,那我们就根据该报文来填充IP-RAW模式下的报文内容即可。

  用wireshark抓取一个电脑端发送的IGMP报文,分析后会发现如果使用IP-RAW模式,那前面的MAC地址和IP信息是不用我们填写了,该内容会在CH395的协议栈中自动填充(MAC-RAW就需要在程序里面填充全部内容了)。其中图2中示IGMP Verrsion:3表示IGMPv3协议;Type报文类型,取值为0x22(画重点,取值关系到发送出去的IGMP类型);Reserverd: 00 保留;Checksum:校验值(这个值可以根据算法算出来的,但本篇文章不涉及算法,所以后文会用最原始的方法填充);Num Group Records 1:已加入1个组;Group Record 224.0.0.251: 加入的组是224.0.0.251。

图2 IGMP报文内容

  分析完报文类型后,根据IP数据包的格式,我们应该需要填充内容为报文类型+保留值+校验值+加入组数量+保留值+要加入的组地址。接下来通过编写程序来实现CH395发送该报文。

  首先,根据官方手册图三示,配置socket为成IP-RAW模式,也就是协议类型为0。

图三 IP-RAW配置

  程序设定了socket3为IP-RAW模式来进行数据发送,目的地址是224.0.0.22(这是一个特殊地址空间,应用上有区别,下面会特别说明),配置程序如下:

const UINT8  Socket3DesIP[4] = {224,0,0,22};                       /* Socket 3目的IP地址(PC) */
void InitSocketParam(void){
   memset(&sockinf[0],0,sizeof(sockinf[0])); /* 将SockInf[0]全部清零*/
memcpy(&sockinf[0].IPAddr, BroadcastIP,sizeof(BroadcastIP)); /* 如果启用UDP SERVER功能,需将目的IP设为广播地址255.255.255.255 */
// sockinf[0].DesPort = Socket0DesPort; /* 目的端口 */
sockinf[0].SourPort= Socket0SourPort; /* 源端口 */
sockinf[0].ProtoType=PROTO_TYPE_UDP; /* UDP模式 */ memset(&sockinf[1],0,sizeof(sockinf[1])); /* 将SockInf[1]全部清零*/
memcpy(&sockinf[1].IPAddr, BroadcastIP,sizeof(BroadcastIP)); /* 如果启用UDP SERVER功能,需将目的IP设为广播地址255.255.255.255 */
// sockinf[1].DesPort = Socket1DesPort; /* 目的端口 */
sockinf[1].SourPort= Socket1SourPort; /* 源端口 */
sockinf[1].ProtoType=PROTO_TYPE_UDP; memset(&sockinf[2],0,sizeof(sockinf[2])); /* 将SockInf[2]全部清零*/
memcpy(&sockinf[2].IPAddr, BroadcastIP,sizeof(BroadcastIP)); /* 如果启用UDP SERVER功能,需将目的IP设为广播地址255.255.255.255 */
// sockinf[1].DesPort = Socket1DesPort; /* 目的端口 */
sockinf[2].SourPort= Socket2SourPort; /* 源端口 */
sockinf[2].ProtoType=PROTO_TYPE_UDP; memset(&sockinf[3],0,sizeof(sockinf[3])); /* 将SockInf[3]全部清零*/
memcpy(CH395Inf.IPAddr,Socket2DesIP,sizeof(Socket3DesIP)); /* 将目的IP地址写入 */
sockinf[3].ProtoType = PROTO_TYPE_IP_RAW; /* IP RAW模式 */
}
 

  设置socket3时,IPRawProto的协议段为02,上面说过IGMP在IP报中的协议类型为2。

const UINT8  IPRawProto = 0x02;    
void CH395SocketInitOpen(void)
{
UINT8 i; /* socket 0为UDP模式 */
CH395SetSocketDesIP(0,sockinf[0].IPAddr); /* 设置socket 0目标IP地址 */
CH395SetSocketProtType(0,sockinf[0].ProtoType); /* 设置socket 0协议类型 */
CH395SetSocketSourPort(0,sockinf[0].SourPort); /* 设置socket 0源端口 */
i = CH395OpenSocket(0); /* 打开socket 0 */
mStopIfError(i); CH395SetSocketDesIP(1,sockinf[1].IPAddr); /* 设置socket 1目标IP地址 */
CH395SetSocketProtType(1,sockinf[1].ProtoType); /* 设置socket 1协议类型 */
CH395SetSocketSourPort(1,sockinf[1].SourPort); /* 设置socket 1源端口 */
i = CH395OpenSocket(1); /* 打开socket 1 */
mStopIfError(i); CH395SetSocketDesIP(2,sockinf[2].IPAddr); /* 设置socket 2目标IP地址 */
CH395SetSocketProtType(2,sockinf[2].ProtoType); /* 设置socket 2协议类型 */
CH395SetSocketSourPort(2,sockinf[2].SourPort); /* 设置socket 2源端口 */
i = CH395OpenSocket(2); /* 打开socket 2 */
mStopIfError(i); /* socket 0为IP RAW模式 */
CH395SetSocketDesIP(3,CH395Inf.IPAddr); /* 设置socket 3目标地址 */
CH395SetSocketProtType(3,sockinf[3].ProtoType); /* 设置socket 3协议类型 */
CH395SetSocketIPRAWProto(3,IPRawProto); /* 设置协议字段,重点此时的IP报协议段为2 */
i = CH395OpenSocket(3); /* 打开socket 3 */
mStopIfError(i);
/* 检查是否成功 */
}

  完成socket3的IP-RAW模式初始化后就可以封装IGMP报文了,根据电脑抓包内容,我们在程序里定义一个Buffer来填充报文。IGMP中Mac地址和目的Ip都是已经在IP-RAW模式下CH395的内部协议栈自动封装,IP报类型也已填入。因此,Buffer中中需要填入0x22,0x00(IGMP类型、保留值);校验值随机填入两位0x01,0x02(后面会根据抓包修改);保留值填3个0x00;入组数量填1;最后填入Group Record信息:类型 :04;Len:00;Num:00;组播地址:e0:00:00:fb。

UINT8  MyBuffer1[24] = {
0x22,0x00,  
0x01,0x02,
0x00,0x00,0x00,0x01,
0x04,0x00,0x00,0x00,0xe0,0x00,0x00,0xfb,
};

  MAC-RAW方式需要自己手动全部添加报文内容(Buffer最后一行为0是为了满足以太网的最小帧64字节):

UINT8  MyBuffer1[] =
{
0x54,0xbf,0x64,0x1c,0x2a,0x9c,0xb4,0x05,0x00,0x00,
0x00,0x00,0x08,0x00,0x45,0x00,0x00,0x2c,0x02,0x98,
0x00,0x00,0x01,0x02,0x13,0x16,0xc0,0xa8,0x01,0x0A,
0xe0,0x00,0x00,0x16,0x22,0x00,0xf9,0x02,0x00,0x00,
0x00,0x01,0x04,0x00,0x00,0x00,0xe0,0x00,0x00,0xfb,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

  在初始化的时候,一定设置一个CH395的TTL值(重点):

    InitSocketParam();                                               /* 初始化socket相关变量 */
CH395SocketInitOpen(); /*打开socket */
CH395SetTTLNum(3,1); /* 设置TTL值 */

  为什么要设置这个TTL值呢?因为我们的目的IP地址是224.0.0.22,而在TCP\IP协议规定中,这个地址其为特殊地址空间不能超过1跳(可以在TCPIP详解1卷中了解),图三示该IP时设置TTL为1的原因。

图三 特殊地址空间的TTL值

  设置完成后,可以在主函数循环调用CH395Senddata函数进行发送:CH395SendData(3,MyBuffer1,24)。提示:一般这个报文需要定时发送,因为有些路由或者交换机在一定时间内没有收到该设备的组播请求会踢出设备,所以应用时可以通过定时器来定时发送该报文。

  CH395初始化完成并启动后,通过Wireshark抓包会发现CH395发出了IGMP报文,但是打开报文分析会出现如图四示红色报错。

  图四 CH395发送的IGMP报文

  报错内容为校验值不对,0x01、0x02应该是0xF9、0x02,那我们就把Buffer中的01、02改成0xF9、0x02再看抓包结果如图五示。

图五 CH395的IGMP请求加入报文

  这时候wiresahrk的报文分析中没有出现红色报错了。但大家可能会发现电脑1.21发出的报文长度为54字节,而CH395的IP1.200发出的长度为60字节,是不是报文还是错的呢?不是,这是因为以太网帧最小为64字节,如果小于64字节就会有padding段填充,同时wireshark会不显示4字节的校验字段,减去该4字节就为60字长,图六示60字节的原因。

图六 CH395的60字长IGMP报文

  到这里CH395的IGMP就没问题了,CH395的IP-RAW和MAC-RAW方式例程已放到下面自取,关于IGMP报文里的校验值其实可以通过算法进行填充,但这里只是教大家一个快速简单的应用方法,如果感兴趣的可以根据网上的算法例程自行添加。

例程链接:https://files.cnblogs.com/files/blogs/805237/Socket-UdpMulticast.rar?t=1700655709&download=true

【WCH以太网接口系列芯片】基于CH395的组播请求(IGMP)的更多相关文章

  1. 海思3516系列芯片SPI速率慢问题深入分析与优化(基于PL022 SPI 控制器)

    海思3516系列芯片SPI速率慢问题深入分析与优化(基于PL022 SPI 控制器) 我在某个海思主控的项目中需要使用SPI接口来驱动一块液晶屏,液晶屏主控为 st7789,分辨率 240x240,图 ...

  2. nxp基于layerscape系列芯片的硬件型号解析

    每一种layerscape系列芯片都有两种硬件型号: RDB 和QDS RDB: Refrence Design Board QDS: QorIQ Development system

  3. 以太网接口TCP/IP协议介绍,说的很容易懂了

      以太网接口TCP/IP协议介绍,说的很容易懂了  TCP/IP协议,或称为TCP/IP协议栈,或互联网协议系列. TCP/IP协议栈(按TCP/IP参考模型划分) 应用层 FTP SMTP HTT ...

  4. [转帖]你不曾见过的国产CPU:可能是最全的龙芯系列芯片家谱(下)

    你不曾见过的国产CPU:可能是最全的龙芯系列芯片家谱(下) https://www.ijiwei.com/html/news/newsdetail?source=pc&news_id=7177 ...

  5. Keil MDK STM32系列(九) 基于HAL和FatFs的FAT格式SD卡TF卡读写

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  6. Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  7. Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401开发

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  8. Nacos系列:基于Nacos的配置中心

    前言 在看正文之前,我想请你回顾一下自己待过的公司都是怎么管理配置的,我想应该会有以下几种方式: 1.硬编码 没有什么配置不配置的,直接写在代码里面,比如使用常量类 优势:对开发友好,开发清楚地知道代 ...

  9. STM32系列芯片命名规范

    1.STM32的基础知识 STM32是意法半导体公司,基于ARM Cortex®-M0,M0+,M3, M4和M7内核生产的系列通用MCU.截止当前时间为止(20190515),STM32有STM32 ...

  10. Keil MDK STM32系列(三) 基于标准外设库SPL的STM32F407开发

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

随机推荐

  1. 使用MD5算法和sha512sum校验和检验文件完整性

    目录 一.前言 二.MD5算法简介 三.什么是校验和 四.使用MD5算法和sha512sum校验和检验文件完整性 五.总结 一.前言 在我们日常生活中,无论是下载文件.传输数据还是备份重要信息,如何确 ...

  2. 个人GAN训练的性能迭代

    使用GAN进行生成图片 损失函数的迭代 DCGAN->Wasserstein GAN-> Wasserstein GAN + Gradient Penalty Discriminator训 ...

  3. 《SQL与数据库基础》23. 读写分离

    目录 读写分离 一主一从 准备 配置 双主双从 准备 配置 主库配置 从库配置 从库关联主库 主库相互复制 双主双从读写分离 本文以 MySQL 为例.以 MyCat 数据库中间件为例,通过 MyCa ...

  4. GitHub Actions CI/CD 工作流实战

    1. 什么是 GitHub Actions 与 workflow ? GitHub Actions 是 GitHub 提供的一种持续集成(CI)和持续部署(CD)的工具,用于自动化软件开发过程中的各种 ...

  5. WPF学习 - 动画基础(1)

    1. WPF中的动画(Animation),是一种属性动画.技术上来说,它是让属性从一个值,变化到另一个值的过程.因此,有两条重要的特性: 1.1 只能为依赖属性应用动画(因为第二条特性). 1.2 ...

  6. Vim深入使用指南

    Vim深入使用指南 Vim是一款功能强大的文本编辑器,被广泛用于编写和编辑各种类型的文档和代码. 安装Vim 可以操作系统下载并安装Vim.在安装完成后,通过在终端中输入vim命令来启动Vim. Vi ...

  7. 好好回答下 TCP 和 UDP 的区别!

    写了这么多篇关于 TCP 和 UDP 的文章,还没有好好聊过这两个协议的区别,这篇文章我们就来开诚布公的谈一谈. 关于 TCP 和 UDP ,想必大家都看过一张这样的图. 有一个小姑娘在对着瓶口慢慢的 ...

  8. 微信小程序 setData accepts an Object rather than some undefined 解决办法

    问题 setData accepts an Object rather than some undefined setData接受一个对象而不是一些定义 让我猜猜, 你一定是在加载index页面(首页 ...

  9. KRPANO PR10最新激活码(破解)分享

    KRPano pr10最新版本激活码下载地址: http://pan.baidu.com/s/1qYv2vO4 适用于最新pr10以及之前版本,解压密码为KRPano技术解密群群号:551278936 ...

  10. nvm、node、vue安装、vue项目创建打包

    nvm.node.vue安装.创建vue项目 nvm作用:可以管理多个版本的node,切换node版本,下载node. 前情提要 参 考:https://zhuanlan.zhihu.com/p/51 ...