gns3 cisco 搭建组播实验

  • 环境
    • gns3安装
  • 网络拓扑
  • 路由器配置
  • 模拟组播
    • 使用c++程序模拟组播源和接受者
  • 实验结果查看
  • 遇到的问题

环境

window10 gns3

gns3安装

放一个别人的链接,blog里面写的很详细,应该怎么安装gns3环境。也有打包的资源。

安装gns

不过不需要完全安装。百度云下载速度我只想吐槽。所以我们只需要下载gns3和一个cisco路由器的镜像,比如c2691,使用本地作为gns的server。

网络拓扑


cloud 是用来连接本地的虚拟环回口,可以查看网络管理,网络适配器是否存在loop口。没有的话,百度一下!
我添加了两个环回口,并配置了ip地址。

路由器配置

enable
//进入配置模式
config t
//开启组播
ip multicast-routing
//配置结构f0/0
interface FastEthernet 0/0
ip address 192.168.10.1 255.255.255.0
//使用igmp dm 模式
ip pim dense-mode

interface FastEthernet 0/1
ip address 192.168.20.1 255.255.255.0
ip pim dense-mode

到这一步组播网络就已经弄好了。

模拟组播

我们需要一个组播源和一个加入组播的成员。
在网上找了一下,发现了VLC media player 可以作为组播源,推送rtp流。使用一个VLC推流,本地一个VLC接收流能够播放MP4,但是wireshark没有抓到包。不知道从那个网卡出去了。看网上说通过配置路由表可以指定出口网卡。然而并没有用。如果有知道的朋友麻烦留言告知一下。
route -p add 224.1.1.4 mask 255.0.0.0 192.168.10.1 metric 3

使用c++程序模拟组播源和接受者

需要改一哈本机地址编译。

组播源
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>#pragma comment(lib, "ws2_32.lib")static const auto LOCAL_IP = "192.168.10.2";
static const auto MULTICAST_GROUP_ADDRESS = "239.255.43.21";
static const unsigned short MULTICAST_GROUP_PORT = 45454;
static const int MSGBUFSIZE = 1024;int init_winsock()
{int iResult;WSADATA wsaData;// Initialize WinsockiResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {printf("WSAStartup failed: %d\n", iResult);return 1;}return 0;
}int test_mcast_send()
{int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd) {printf("socket error!!!\n");perror("socket:");return -1;}int ttl = 60; /* max = 255 *///int aaret = setsockopt(sockfd, IPPROTO_IP, IP_TTL, (char*)&ttl, sizeof(ttl));int aaret = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));  //设置组播TTif (-1 == aaret) {printf("IP_TTL error!!!\n");perror("setsockopt:");closesocket(sockfd);return -1;}int reuse = 1;if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(reuse)) < 0) {perror("Setting SO_REUSEADDR error");closesocket(sockfd);return -1;}struct sockaddr_in addr = {};addr.sin_family = AF_INET;addr.sin_port = htons(MULTICAST_GROUP_PORT);addr.sin_addr.s_addr = INADDR_ANY;int addr_len = sizeof(addr);int ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr));if (-1 == ret) {printf("bind localaddr error!!!\n");perror("bind:");closesocket(sockfd);return -1;}unsigned long if_addr = inet_addr(LOCAL_IP);ret = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&if_addr, sizeof(if_addr));if (-1 == ret) {printf("IP_MULTICAST_IF error!!!\n");perror("setsockopt:");closesocket(sockfd);return -1;}char host[1024] = { 0 };gethostname(host, 1024);int msgNo = 0;char msg[1024] = { 0 };addr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP_ADDRESS);while (true) {//sprintf(msg, "Groupcast Message %s No.%d", host, msgNo++);sprintf(msg, "ControlCenterMessage %d", msgNo++);int ret = sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)&addr, addr_len);if (ret < 0) {perror("sendto");return -1;}else {printf("Sent msg: %s\n", msg);}Sleep(1000);}return 0;
}int main()
{int ret = init_winsock();if (0 != ret) { return ret; }ret = test_mcast_send();getchar();
}
接收者
//#include <Windows.h>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>#pragma comment(lib, "ws2_32.lib")static const auto LOCAL_IP = "192.168.20.5";
static const auto MULTICAST_GROUP_ADDRESS = "239.255.43.21";
static const unsigned short MULTICAST_GROUP_PORT = 45454;
static const int MSGBUFSIZE = 1024;int init_winsock()
{int iResult;WSADATA wsaData;// Initialize WinsockiResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {printf("WSAStartup failed: %d\n", iResult);return 1;}return 0;
}int test_multicast_with_local_ip()
{int ret = 0;int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd) {printf("socket error!!!\n");perror("socket:");return -1;}int reuse = 1;if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(reuse)) < 0) {perror("Setting SO_REUSEADDR error");closesocket(sockfd);return -1;}/*test ip*/struct sockaddr_in localaddr = { 0 };localaddr.sin_family = AF_INET;localaddr.sin_port = htons(MULTICAST_GROUP_PORT);localaddr.sin_addr.s_addr = /*inet_addr(LOCAL_IP)*/ htonl(INADDR_ANY);ret = bind(sockfd, (struct sockaddr*)&localaddr, sizeof(struct sockaddr));if (-1 == ret) {printf("bind localaddr error!!!\n");perror("bind:");closesocket(sockfd);return -1;}/*设置是否支持本地回环接收*//*int loopBack = 1;ret = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&loopBack, sizeof(loopBack));if (-1 == ret) {printf("setsockopt broadcaset error!!!\n");perror("setsockopt:");closesocket(sockfd);return -1;}*//*将本地socket添加到多播组中,注意,此处针对struct ip_mreq结构体需要填充两个成员,成员ipmr.imr_interface.s_addr的值指定的是将要发送的网卡的ip地址,成员impr.imr_multiaddr指定的是组播地址;如果指定为INADDR_ANY则系统会绑定一个默认网卡的具体ip(根据默认网关选择),则会出现特定网卡可以发送和接收组播信息,另一网卡不可以。即指定INADDR_ANY并不能把所有网卡都添加多播组中,必须明确指定对应网卡ip才可以。*///struct in_addr addr = { 0 };//addr.s_addr = inet_addr(local_ip);struct ip_mreq ipmr = { 0 };ipmr.imr_interface.s_addr = inet_addr(LOCAL_IP) /*(INADDR_ANY)*/;ipmr.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP_ADDRESS);int len = sizeof(ipmr);ret = setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&ipmr, len);if (-1 == ret) {printf("set error IP_ADD_MEMBERSHIP %d\n", WSAGetLastError());perror("setsockopt:");closesocket(sockfd);return -1;}/*此处指定组播数据的出口网卡,如果不设置则会根据路由表指定默认路由出口*//*if (-1 == setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&addr, sizeof(addr))) {printf("set error IP_MULTICAST_IF %s\n", local_ip);perror("Setting IP_MULTICAST_IF error:");closesocket(sockfd);sockfd = -1;}*//*struct timeval tv;tv.tv_sec = 2;tv.tv_usec = 0;ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));if (-1 == ret) {printf("setsockopt recvtimeout error!!!\n");perror("setsockopt:");closesocket(sockfd);return -1;}*//* now just enter a read-print loop */char msgbuf[MSGBUFSIZE];int nbytes = 0;//localaddr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP_ADDRESS);localaddr.sin_addr.s_addr = inet_addr(LOCAL_IP);while (1) {int addrlen = sizeof(localaddr);if ((nbytes = recvfrom(sockfd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *) &localaddr, &addrlen)) < 0) {perror("recvfrom");return -1;}msgbuf[nbytes] = 0;puts(msgbuf);}return 0;
}int test_multicast()
{int fd;/* create what looks like an ordinary UDP socket */if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket");return(1);}/**** MODIFICATION TO ORIGINAL *//* allow multiple sockets to use the same PORT number */u_int yes = 1;            /*** MODIFICATION TO ORIGINAL */if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(yes)) < 0) {perror("Reusing ADDR failed");return(1);}/*** END OF MODIFICATION TO ORIGINAL *//* set up destination address */struct sockaddr_in addr = {};memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY); /* N.B.: differs from sender */addr.sin_port = htons(MULTICAST_GROUP_PORT);/* bind to receive address */if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {perror("bind");return(1);}/* use setsockopt() to request that the kernel join a multicast group */struct ip_mreq mreq = {};mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP_ADDRESS);//mreq.imr_interface.s_addr = htonl(INADDR_ANY);if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) < 0) {perror("IP_ADD_MEMBERSHIP");//return(1);}/* now just enter a read-print loop */int nbytes = 0;int addrlen = sizeof(addr);char msgbuf[MSGBUFSIZE] = {};while (1) {if ((nbytes = recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *) &addr, &addrlen)) < 0) {perror("recvfrom");return(1);}msgbuf[nbytes] = 0;printf("receive:%s\n", msgbuf);}return 0;
}int main()
{int ret = init_winsock();if (0 != ret) { return ret; }ret = test_multicast_with_local_ip();//ret = test_multicast();getchar();
}

实验结果查看

本来接收者可以直接打印出消息的。后面抓包发现,组播流被封装在了负载里面。所有只有抓包才能查看结果了。

遇到的问题

1:添加了环回口后,连接cloud和路由器报错:网卡打开失败.
解决:电脑没有安装winpcap。 或者以前安装过,下载不干净,导致安装失败。卸载干净后重新安装。
2:组播包到达路由器后没有被转发。
解决:网上搜到一篇写的很详细的排查过程。特别厉害。
igmp错误排查
我的问题是构建的组播报文ttl值为1.导致路由器直接将包丢弃了。修改组播报文ip.tll为60.

igmp组播实验 @yx相关推荐

  1. IGMP组播加入失败原因

    IGMP组播加入不成功 最近在做一个项目,需要用到组播的功能,程序调试完了以后,在XP下可以正常实现组播,不过到了WIN7下以后就无法使用组播了,搞了很久,最后通过与工程师沟通,发现是IGMP(组播协 ...

  2. 组播学习之——IGMP协议简介

    CSDN文章转载地址 组播学习之--IGMP协议简介 IGMP 是Internet Group Management Protocol(互联网组管理协议)的简称.它是TCP/IP 协议族中负责IP 组 ...

  3. 华为数通笔记-组播协议介绍之IGMP

    组播网络需要基于多种组播协议才能建立转发路径: 工作在成员端网络的主要是IGMP(Internet Group Management Protocol,因特网组管理协议)协议 用于告知组播网络,组成员 ...

  4. 网工笔记(三):IP Multicast组播技术

    IP多路组播技术,英文为IP Multicast,  就是英文文档里经常说到的BUM报文里的大M.这是一门特别的技术,它从2层到3层协议mac地址到IP地址都自成一体.很多网工同行只在IE考试里学习了 ...

  5. 【学习笔记】网络层——网络层设备、移动IP、IP组播

    文章目录 一. 网络层设备 1)三层设备的区别 2)路由表与路由转发 二. 移动IP ① 定义 相关术语: 实际过程: 三. IP组播 ① IP数据报的三种传输方式 ② IP组播地址 ③ IGMP协议 ...

  6. 组播IGMP-原理介绍+报文分析+配置示例

    个人认为,理解报文就理解了协议.通过报文中的字段可以理解协议在交互过程中相关传递的信息,更加便于理解协议. 因此本文将在IGMPv2协议报文的基础上进行介绍,以详细介绍主机-路由器IGMP组播协议.I ...

  7. ZigBee协议栈组播

      组播描述的就是网络中所有节点设备被分组后组内相互通信的过程,确定通信对象的就是节点的组号.关注SampleApp.c中的2项内容:   1. 组播afAddrType_t的类型变量: afAddr ...

  8. 【实验】通过IGMP实现接收组播视频信息案例

    拓扑图 规格 适用于所有版本.所有形态的AR路由器. 组网需求 RouterA的GE0/0/1连接组播源,GE0/0/0连接RouterB.RouterB的GE0/0/1连接RouterA,GE0/0 ...

  9. 55、组播配置实验之PIM Sparse Mode静态指定RP

    1.PIM Sparse Mode简介 2.实验拓扑 3.基础配置 R1配置 interface Serial0/1 ip address 12.1.1.1 255.255.255.0 interfa ...

最新文章

  1. Linux-鸟菜-5-目录配置-FHS
  2. golang中的bufio
  3. php如何按降序,PHP数组如何按键名实现降序排列
  4. 免费节假日API 更新新功能了 新增农历信息返回
  5. 如何理解typedef void
  6. SQL SERVER 2012/2014 链接到 SQL SERVER 2000的各种坑
  7. Vue使用Emoji表情
  8. uniapp 获取屏幕高度并赋值
  9. 学专业计算机的配置,大学学计算机专业的学生电脑普遍配置是什么呢?
  10. 字符画-Python
  11. [转]Golang中goroutine的调度器详解
  12. 跳转页面下载文件需要附带Token请求头,如何实现ajax下载?
  13. 【Linux】文件类型
  14. 基于Singer混沌映射的麻雀搜索算法-附代码
  15. 2006年F1第五站德国纽伯格林
  16. 阿里云免费领取云服务器测试题答案
  17. 激光SLAM与视觉SLAM的区别
  18. python父亲节祝福_2019父爱如山的父亲节最新祝福问候句子大全
  19. linux下安装程序
  20. 微软全球执行副总裁--陆奇博士

热门文章

  1. 基于STM32的智能风扇的制作
  2. Tableau可视化设计案例-05Tableau进阶
  3. 中科蓝汛----指示灯配置使用方法
  4. java中的双引号和单引号
  5. 深度学习LSTM模型对股票分析预测
  6. 给图片加上水印php视频,如何使用PHP给图片加水印
  7. 【数据结构课程设计】关键路径问题
  8. 蚂蚁微贷互动营销技术体系实践 1
  9. 9个主流的开源许可协议
  10. 个人用户永久免费,可自动升级版Excel插件,使用VSTO开发,Excel催化剂功能第11波-快速批量插入图片...