在上一篇文章中,我们通过直连电脑测试了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. MyBatis Mapper映射处理CLOB和BLOB类型

    ​Mybatis的MapperXML映射文件应该处理数据库字段类型为CLOB和BLOB类型的数据呢?首先我们先看下CLOB和BLOB这两种数据类型的介绍. 介绍 使用Mybatis时涉及到两种特殊类型 ...

  2. [ABC149E] Handshake

    2023-03-06 题目 题目传送门 翻译 翻译 难度&重要性(1~10):4 题目来源 AtCoder 题目算法 二分 解题思路 因为按照贡献从大到小握手一定是最优的,所以将 \(a\) ...

  3. 2.4 PE结构:节表详细解析

    节表(Section Table)是Windows PE/COFF格式的可执行文件中一个非常重要的数据结构,它记录了各个代码段.数据段.资源段.重定向表等在文件中的位置和大小信息,是操作系统加载文件时 ...

  4. 使用GPU搭建支持玛雅(Maya)和Adobe AI,DW,PS的职校云计算机房

    背景 学校为职业学校,计算机教室需要进行Maya.Adobe Illustrator.Adobe Dreamweaver.Adobe PhotoShop等软件的教学.每个教室为35用户.资源需求为4核 ...

  5. 2023 ICPC 网络赛 I

    没留够时间准备导致开考的时候耽搁了 开场我先写缺省源,抄串了一行,后面才发现...然后看了 L 发现是签到,此时 ddw 会了 A 让 zsy 上去写,我等了一会才把 zsy 撵下来写 L 是个失误 ...

  6. 文章《Semantic Kernel —— LangChain 的替代品?》的错误和疑问 探讨

    微信公众号文章 Semantic Kernel -- LangChain 的替代品?[1] ,它使用的示例代码是Python ,他却发了这么一个疑问: 支持的语言对比(因为 Semantic Kern ...

  7. Linux系列教程——Linux文件编辑、Linux用户管理

    @ 目录 1 Linux基本权限 1.权限基本概述 1.什么是权限? 2.为什么要有权限? 3.权限与用户之间的关系? 4.权限中的rwx分别代表什么含义? 2.权限设置示例 1.为什么要设定权限,我 ...

  8. OSPF常用配置和常用的查看命令

    转载请注明出处: 1.启动OSPF进程,进入OSPF视图. [Huawei] ospf [ process-id | Router ID Router ID ] 路由器支持OSPF多进程,进程号是本地 ...

  9. client-go实战之六:时隔两年,刷新版本继续实战

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 时隔两年,<client-go实战>被激活 ...

  10. CF431C

    题目简化和分析: k叉树,乍一看好像是树论,但我们通过分析条件,发现它每个阶段要做的事情一样,皆为:\(1\sim k\) 中选数字,这就很明显是DP. \(\mathit{f}_{i,0}\) 表示 ...