我看到了不踏实的自己,我看到了不满足的自己,我看到了永远胡思乱想的自己,我看到了自卑的自己,我看到了不快乐的自己。我讨厌这样的自己。
无论生活还是工作,如果不能静下心来坦然去面对和经历,那么那样的我铁定是不快乐的,现在的我即如此,脑子里总是充斥着太多烦扰,是不是所有的教训都要经历惨痛才能不会再犯呢?
好吧,我用心学习,希望学习能少带给我一些烦恼。有一段时间没在这里更新,怎一个懒字了得。
IGMP,TCP\IP协议群中的一个,今天让我来见见它的庐山真面目,一段时间以前的总结,还是要放在这里更舒服,网络的魅力。
1、单播,组播,广播
单播:是指对特定主机进行数据传输,例如某个主机发送IP数据包,即数据头里面有非常具体的目的地址,即网卡的MAC地址。
广播:是指主机针对某一个网络上的所有主机发送数据包。这样传送的数据头里面的目的MAC地址则为: FF-FF-FF-FF-FF-FF , 网络内所有的主机都会收到这个广播数据 .
组播,就是给一组特定的机器发送数据,多播的MAC地址是最高字节的低位为1, 例 如01-00-00-00-00-00。多播组的地址是D类IP,规定是224.0.0.0-239.255.255.255。
IGMP是IP组播的基础,在IP协议出现以后,为了加入对组播的支持,IGMP产生了, 所以概括的说 IGMP所做的实际上就是告诉路由器,在这个路由器所在的子网内有人对发送到某一个组播组的数据感兴趣,这样当这个组播组的数据到达后,路由器就不会抛弃它,而是把他转送给所有感兴趣的客户。假如不同子网内的A,B要进行组播通信,那么,位与A,B之间的所有路由器必须都要支持IGMP协议,否则A,B之间不能进行通信。
2 、IGMP基础
IGMP实现的功能是双向的, 通过IGMP协议 ,一方面, 主机通知本地路由器希望加入并接收某个特定组播组的信息;另一方面,路由器通过IGMP协议周期性地查询局域网内某个已知组的成员是否处于活动状态。 (即该网段是否仍有属于某个组播组的成员)。所以可知IGMP主要有2个类型,类型为1说明是由多播路由器发出的查询报文,为2说明是主机发出的报告报文。通过IGMP,在路由器中记录的信息是某个组播组是否在本地有组成员,而不是组播组与本机之间的对应关系。
IGMP协议是TCP\IP协议族中的一个协议,被当作IP层的一部分。通过IP数据报进行传输,即IGMP报文封装在IP数据报中。IGMP报文通过IP首部中协议字段值为2来指明。 图1显示了IGMP如何封装在IP数据报中。
图1:IGMP封装在IP数据报中
下图显示了长度为8字节的IGMP报文结构
图2:IGMP报文结构
IGMP类型为1说明是由多播路由器发出的查询报文,为2说明是主机发出的报告报文。检验和的计算和ICMP协议相同。组地址为D类IP地址。在查询报文中组地址设置为0,在报告报文中组地址为要参加的组地址。
3、 如何实现UDP组播?
Windows 提供的winsock机制,先后提供了两种组播的实现方式,winsock1里 通过setsockopt IP_ADD_MEMBERSHIP加入一个组播组,winsock2里,则通过WSAJoinLeaf来实现,这里使用第2种,主要有以下几个步骤:
1) . 建立支持数据报的socket(用WSASocket建立socket) 并 设置组播的一些属性
2) . 把socket和本地的一个端口绑定(以后会通过这个端口进行数据的收发)
3). 通过WSAJoinLeaf加入一个组播组
4). 通过sendto / recvfrom进行数据的收发
5). 直接关闭socket,
6). 退出组播组
#pragma comment(lib, "ws2_32.lib") //ws2_32.lib这个是必要的,因为调用WSAJoinLeaf是系统的一个函数,这个函数的导出表在ws2_32.lib中,通过它就能找到对应的函数了。
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData = {0}; //wsadata结构体用于存放windows socket初始化信息
WSAStartup(MAKEWORD(2, 0), &wsaData); //WSAStartup,必须调用的第一个windows socket函数,用于指明sockets api的版本号,及实现的细节
//SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
SOCKET s = WSASocket(
AF_INET,
SOCK_DGRAM,
0,
NULL,
0,
WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF
);
//wsasocket创建一个与指定传送服务提供者捆绑的套接口
sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(4567);
int nRet = bind(s, (sockaddr*)&addr, sizeof(sockaddr_in));
sockaddr_in addrGroup = {0};
addrGroup.sin_addr.s_addr = inet_addr("225.0.0.1");
addrGroup.sin_family = AF_INET;
addrGroup.sin_port = htons(4567);
//创建socket的相关信息
SOCKET leaf = WSAJoinLeaf(
s,
(sockaddr*)&addrGroup,
sizeof(sockaddr_in),
NULL,
NULL,
NULL,
NULL,
0x04
);
WSACleanup();
//通过WSAJoinLeaf加入一个组播组
return 0;
}
运行该程序,通过wireshark抓包工具可以更清晰地认识UDP组播的实现,
3、 IGMP实现原理
l 如何加入 一个多播组?
多播的基础就是一个进程的概念(操作系统执行的一个程序),该进程在一个主机的给定接口上加入了一个多播组。在一个给定接口上的多播组中的成员是动态的—它随时因进程加入和离开多播组而变化。
这里所指的进程必须以某种方式在给定的接口上加入某个多播组。进程也能离开先前加入的多播组。
l IGMP如何报告和查询?
多播路由器使用IGMP报文来记录与该路由器相连网络中组成员的变化情况。使用规则如下:
1)当第一个进程加入一个组时,主机就发送一个IGMP报告。如果一个主机的多个进程加入同一组,只发送一个IGMP报告。这个报告被发送到进程加入组所在的同一接口上。
2)进程离开一个组时,主机不发送IGMP报告,即便是组中的最后一个进程离开。主机知道在确定的组中已不再有组成员后,在随后收到的IGMP查询中就不再发送报告报文。
3)多播路由器定时发送IGMP查询来了解是否还有任何主机包含有属于多播组的进程。多播路由器必须向每个接口发送一个IGMP查询。因为路由器希望主机对它加入的每个多播组均发回一个报告,因此IGMP查询报文中的组地址被设置为0。
4)主机通过发送IGMP报告来响应一个IGMP查询,对每个至少还包含一个进程的组均要发回IGMP报告。
使用这些查询和报告报文,多播路由器对每个接口保持一个表,表中记录接口上至少还包含一个主机的多播组。当路由器收到要转发的多播数据报时,它只将该数据报转发到(使用相应的多播链路层地址)还拥有属于那个组主机的接口上。
IGMP 具有三种版本,即 IGMP v1、v2 和 v3。
· IGMPv1: 主机可以加入组播组。没有离开信息(leave messages)。路由器使用基于超时的机制去发现其成员不关注的组。
· IGMPv2: 该协议包含了离开信息,允许迅速向路由协议报告组成员终止情况,这对高带宽组播组或易变型组播组成员而言是非常重要的。
· IGMPv3: 与以上两种协议相比,该协议的主要改动为:允许主机指定它要接收通信流量的主机对象。来自网络中其它主机的流量是被隔离的。IGMPv3 也支持主机阻止那些来自于非要求的主机发送的网络数据包 .
4、IGMP所带来的安全问题?
IGMP攻击在win2000以前比较严重,常用的攻击方式:
1、IGMP攻击是指向装有Windows操作系统的机器发送长度和数量都较大的IGMP数据包,使得遭受攻击的主机蓝屏下线。
2、伪造一个目的地址是单个ip, 但ip上层协议指定为IGMP,系统会为你打造一个igmp报头, 因为为组播使用D类地址,所以系统不知如何处理,造成崩溃.
5、参考资料
《TCP/IP详解》
http://blog.csdn.net/zhangjie_xiaoke/archive/2008/11/28/3403892.aspx
保留的多播地址:
224.0.0.0 - Base address
224.0.0.1 - 网段中所有支持多播的主机
224.0.0.2 - 网段中所有支持多播的路由器
224.0.0.4 - 网段中所有的DVMRP路由器
224.0.0.5 - 所有的OSPF路由器
224.0.0.6 - 所有的OSPF指派路由器
224.0.0.7 - 所有的ST路由器
224.0.0.8 - 所有的ST主机
224.0.0.9 - 所有RIPv2路由器
224.0.0.10 - 网段中所有支的路由器
224.0.0.11 - Mobile-Agents
224.0.0.12 - DHCP server / relay agent.
224.0.0.13 - 所有的PIM路由器
224.0.0.22 - 所有的IGMP路由器
224.0.0.251 - 所有的支持组播的DNS服务器