博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

组播问题 【好】

Posted on 2016-11-18 14:15  bw_0927  阅读(2467)  评论(1编辑  收藏  举报

http://blog.csdn.net/justlinux2010/article/details/11140383

http://wiki.treck.com/setsockopt

 

omping 命令

 

tcpdump

netstat

dropwatch

 

集群之间的探活用的是组播消息,出现这种问题肯定是因为接收组播报文出了问题。

之前遇到过一次是因为网关配置的不一致导致的

 

"netstat -gn"命令来查看当前哪些网卡加入了哪些组播组【只针对消息的接收方,在消息的发送方是没办法netstat -gn出来的

 

[root@shanghai-OA-pm-2K1code-10-1-22-246 ~]# netstat -gn
IPv6/IPv4 Group Memberships
Interface       RefCnt Group
--------------- ------ ---------------------
lo              1      224.0.0.1      //lo具有组播能力
eth0            1      224.0.0.1      //eth0具有组播能力
eth1            1      238.2.2.2
eth1            1      238.1.2.138
eth1            1      238.1.2.107
eth1            1      238.1.2.106
eth1            1      238.1.2.104
eth1            1      238.1.2.101
eth1            1      224.0.0.1

netstat -gn  无法显示对应的程序端口

netstat -anu   作为补充使用,通过端口可找到对应的程序

[root@shanghai-OA-pm-2K1code-10-1-22-246 ~]# netstat -anu
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State      
udp        0      0 238.1.2.138:10138           0.0.0.0:*                               
udp        0      0 0.0.0.0:161                 0.0.0.0:*                               
udp        0      0 0.0.0.0:53                  0.0.0.0:*                               
udp        0      0 10.1.22.246:42814           10.221.75.116:1514          ESTABLISHED 
udp        0      0 0.0.0.0:43740               0.0.0.0:*                               
udp        0      0 238.1.2.101:10101           0.0.0.0:*                               
udp        0      0 238.1.2.104:10104           0.0.0.0:*                               
udp        0      0 238.1.2.106:10106           0.0.0.0:*                               
udp        0      0 238.1.2.107:10107           0.0.0.0:*                 

 

In practice UDP sockets which are used to receive multicast traffic are usually bound to address 0.0.0.0. These can receive UDP packets for all unicast and multicast addresses。

http://2849159106.blog.51cto.com/7881853/1851224

组播地址
224.0.0.0到239.255.255.25

从224.0.0.0到239.255.255.255都是这样的地址。224.0.0.1特指所有主机, 224.0.0.2特指所有路由器。这样的地址多用于一些特定的程序以及多媒体程序。如果你的主机开启了IRDP(Internet路由发现协议,使用组播功能)功能,那么你的主机路由表中应该有这样一条路由。
224.0.0.5指OSPF路由器,地址多用于一些特定的程序以及多媒体程序

http://blog.sina.com.cn/s/blog_3d8529400100h2b9.html

多播组中的成员是与接口相关联的,一个进程可以在多个接口上加入同一多播组

一个初始TTL为0的多播数据报将被限制在同一主 机。在默认情况下,待传多播数据报的TTL被设置为1,这将使多播数据报仅局限在同一子网内传送。更大的TTL值能被多播路由器转发。

224.0.0.0到224.0.0.255的特殊地址空间是打算用于多播范围不超过1跳的应用。不管TTL值是多少,多播路由器均不转发目 的地址为这些地址中的任何一个地址的数据报

IP地址224.0.0.1.该地址被称为所有主机组地址。它涉及在一个物理网络中的所有具备多播能力的主机和路由器。当接口初始化后,所有具备多播能力接口上的主机均自动加入这个多播组。

 

 

  

 

后面使用"netstat -gn"命令来查看当前网卡上加入的组播组。用这个命令在机器上查看,发现加入的组播地址224.0.1.37绑定在eth0上,而本来要接收组播消息的fd绑定的IP地址是eth1上的地址。觉得应该是这里的问题。
《IP Multicast Extensions for 4.3BSD UNIX and related systems》上看到,如果在加入组播组时,本地接口地址imr_interface设置的是INADDR_ANY时,选择默认的组播接口,也就是让内核来选择。根据现在的情况来看,内核在选择的时候会选择默认网关使用的设备,我这里使用的就是eth0。如果指定的接口地址的话,就会使用地址所在的网络接口作为组播组使用的网络接口。
 
现在基本可以确定丢包的原因了。两个机器的eth0和eth1网卡上设置的IP地址是不同网段的,eth0是9段的IP地址,eth1是4段的IP地址。发送组播消息时,使用的是4段的IP地址,所以接收组播消息的机器上数据包应该由eth1代表的4网段网卡来接收,但是加入组播组的网卡是eth0,所以数据包到达eth1时会查找路由失败,在ip_rcv_finish()中会将数据包丢弃。
http://www.cnblogs.com/my_life/articles/6100830.html
 
找到问题原因,立即修改代码。在加入组播组时,将imr_interface设置为指定的本地IP地址。重新编译,启动后,用“netstat -gn”发现现在组播地址所在的设备和绑定的接口相同,测试没有问题。
 
http://colobu.com/2014/11/07/linux-muticast-setting-with-netty/

运行ifconfig -a, 如果在输出中有如下的信息,则当前的内核支持multicast。

UP BROADCAST RUNNING MULTICAST

 

如果没有这样的信息, 尝试下面的命令

ifconfig eth0 multicast

 

再运行ifconfig -a, 如果的确没有UP BROADCAST RUNNING MULTICAST, 需要重新编译内核。
设置内核配置如下:

  • CONFIG_IP_MULTICAST=y
  • CONFIG_IP_ROUTER=y
  • CONFIG_IP_MROUTE=y
  • CONFIG_NET_IPIP=y
    默认Red Hat / Fedora/ Cent OS内核都支持multicast。
  • ====

 

 

http://blog.chinaunix.net/uid-31125416-id-5705162.html

2.2 实现IP组播的前提条件 

实现IP组播传输,则组播源和接收者以及两者之间的下层网络都必须支持组播。这包括以下几方面: 
●主机的TCP/IP实现支持发送和接收IP组播; 
●主机的网络接口支持组播; 
●有一套用于加入、离开、查询的组管理协议,即IGMP(v1,v2); 
●有一套IP地址分配策略,并能将第三层IP组播地址映射到第二层MAC地址; 
●支持IP组播的应用软件; 
所有介于组播源和接收者之间的路由器、集线器、交换机、TCP/IP栈、防火墙均需支持组播; 

 

http://stackoverflow.com/questions/379015/udp-broadcast-packets-across-subnets

 

Yes, and no.

It's actually do-able, so long as the intervening routers don't have no ip directed-broadcasts or similar configured. However these days that's the default because allowing normal broadcasts to traverse routers is a DoS problem.

If you really want to broadcast across subnets then you should be using IP Multicast instead. That still requires that the intervening routers are configured appropriately, but it is the "right" way to do it.

 

=============================================

http://www.kohala.com/start/mcast.api.txt

  • Sending IP Multicast Datagrams 发送方

IP multicasting is currently supported only on AF_INET sockets of type SOCK_DGRAM and SOCK_RAW, and only on subnetworks for which the interface driver has been modified to support multicasting.

To send a multicast datagram, specify an IP multicast address in the range 224.0.0.0 to 239.255.255.255 as the destination address in a sendto() call.
By default, IP multicast datagrams are sent with a time-to-live (TTL) of 1, which prevents them from being forwarded beyond a single subnetwork. 
Multicast datagrams with TTL greater than one may be delivered to more than one subnet if there are one or more multicast routers attached to the first-hop subnet. 组播包想跨域子网,除了TTL大于1,还需要子网间的路由器对组播的支持
multicast datagrams with initial TTL   0 are restricted to the same host
multicast datagrams with initial TTL   1 are restricted to the same subnet
multicast datagrams with initial TTL  32 are restricted to the same site
multicast datagrams with initial TTL  64 are restricted to the same region
multicast datagrams with initial TTL 128 are restricted to the same continent
multicast datagrams with initial TTL 255 are unrestricted in scope.

 

The multicast router accompanying this release refuses to forward any multicast datagram with a destination address between 224.0.0.0 and 224.0.0.255, inclusive, regardless of its TTL.  This range of addresses is
reserved for the use of routing protocols and other low-level topology discovery or maintenance protocols, such as gateway discovery and group membership reporting.  The current specification for IP multicasting requires
this behavior only for addresses 224.0.0.0 and 224.0.0.1;   路由器拒绝转发[224.0.0.0, 224.0.0.255]之间的组播报文,无论TTL是什么值。因为这些地址作为保留地址,有特殊用处

Each multicast transmission is sent from a single network interface, even if the host has more than one multicast-capable interface. 【组播数据始终只能由同一个网卡发出去,即使它是个多网卡机器
(If the host is also serving as a multicast router, a multicast may be FORWARDED to interfaces other than originating interface, provided that the TTL is greater than 1.) 如果发送组播数据的主机它同时还是一个组播路由器,只要TTL大于1,组播数据可能会从另外的网卡上forward出去。

The system manager establishes the default interface to be used for multicasting as part of the installation procedure, described below. 系统管理员在安装系统时会指定默认的组播网卡
A socket option is available to override the default for subsequent transmissions from a given socket: struct in_addr addr; setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr)) //通过该API可以覆盖默认的组播数据发送网卡。 where "addr" is the local IP address of the desired outgoing interface.

An address of INADDR_ANY may be used to revert to the default interface. 重新设置INADDR_ANY可以恢复默认的组播网卡设置

The local IP address of an interface can be obtained via the SIOCGIFCONF ioctl. //获取网卡IP的方法
To determine if an interface supports multicasting, fetch the interface flags via the SIOCGIFFLAGS ioctl and see if the IFF_MULTICAST flag is set. //查看网卡是否支持组播,通常应用程序没必要使用该选项,因为该选项主要是给路由器等底层网络设备使用的。
(Normal applications should not need to use this option; it is intended primarily for multicast routers and other system services specifically concerned with internet topology.)


If a multicast datagram is sent to a group to which the sending host itself belongs (on the outgoing interface), a copy of the datagram is, by default, looped back by the IP layer for local delivery.  
如果发送方向一个组播组发送了一个组播数据,但发送方本身自己也加入了那个组播组,默认的行为是,IP层会拷贝一份数据包loop back给自己

Another socket option gives the sender explicit control over whether or not subsequent datagrams are looped back: u_char loop; setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) //同样,也存在一个选项可以控制,是否接收loop back回来的数据包拷贝。 where "loop" is 0 to disable loopback, and 1 to enable loopback. This option provides a performance benefit for applications that may have no more than one instance on a single host (such as a router or a mail demon), by eliminating the overhead of receiving their own transmissions. 对于那些只扮演一个组播角色的主机来说,禁用loop back是一种性能优化,减少了不必要的环路数据的传输
It should generally not be used by applications for which there may be more than one instance on a single host (such as a conferencing program) or for which the sender does not belong to the destination group (such as a time querying program). 但对于那些同时扮演了多个组播角色(既是发送方,又是接收方)的主机来说,(例如视频会议:因为发送一个组播视频数据,同时发送方自身也需要把视频数据展现出来),例如组播数据的发送方自身并不属于目的组播组(例如时间查询程序),类似这样的情形,通常并不推荐应用程序禁用loop back选项
A multicast datagram sent with an initial TTL greater than 1 may be delivered to the sending host on a different interface from that on which it was sent, if the host belongs to the destination group on that other interface.
The loopback control option has no effect on such delivery. 如果被发送的组播数据的TTL大于1,并且该主机通过另外一个网卡加入到了目标组播组内,它可能会从不同的网卡上收到loop back回来的组播数据, 这中情况loopback选项不起作用。

有可能发组播数据是一个网卡,收组播数据是另外一个网卡。
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr)) 控制的是发送组播数据的网卡
struct ip_mreq mreq;
setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) 控制的是接收组播数据的网卡


  • Receiving IP Multicast Datagrams 接收方

Before a host can receive IP multicast datagrams, it must become a member of one or more IP multicast groups.  //在能接收组播数据前,必须先加入对应的组播组
A process can ask the host to join a multicast group by using the following socket option: struct ip_mreq mreq; setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) where "mreq" is the following structure: struct ip_mreq { struct in_addr imr_multiaddr; /* multicast group to join */ struct in_addr imr_interface; /* interface to join on */ 加入组播组时所使用的网卡 } Every membership(组播组) is associated with a single interface, and it is possible to join the same group on more than one interface. 每一个组都必须绑定一个网卡,可以把多个网卡同时加入同一个组播组
"imr_interface" should be INADDR_ANY to choose the default multicast interface, or one of the host's local addresses to choose a particular (multicast-capable) interface.
imr_interface字段要么是INADDR_ANY(使用系统默认的网卡加入组),要么是本机的某个网卡对应的IP
Up to IP_MAX_MEMBERSHIPS (currently 20) memberships may be added on a single socket. 一个网卡最多可以加入20个组播组
 
To drop a membership, use:

	struct ip_mreq mreq;
	setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq))

where "mreq" contains the same values as used to add the membership.  The memberships associated with a socket are also dropped when the socket is closed or the process holding the socket is killed.  //当socket被关闭,或者socket所在的进程结束,该socket将会自动离开组播组
However, more than one socket may claim a membership in a particular group, and the host will remain a member of that group until the last claim is dropped. The memberships associated with a socket do not necessarily determine which datagrams are received on that socket. (socket被加入了某个组播组,但并不代表就能从该socket上接收到组内的组播数据
Incoming multicast packets are accepted by the kernel IP layer if any socket has claimed a membership in the destination group of the datagram;
however, delivery of a multicast datagram to a particular socket is based on the destination port (or protocol type, for raw sockets), just as with unicast datagrams.
组播数据能不能被socket所收到,由数据包中的目标端口来决定,就和UDP单播一样

To receive multicast datagrams sent to a particular port, it is necessary to bind to that local port, leaving the local address unspecified (i.e., INADDR_ANY).
为了能够收到被发往某个端口的组播数据报,必须把sock绑定到对应的本地端口,本地地址保留为INADDR_ANY(表示我能接收任何地址发向特定端口的数据)
http://www.cnblogs.com/my_life/articles/6065752.html


More than one process may bind to the same SOCK_DGRAM UDP port if the bind() is preceded by:  多个进程可以绑定同一个UDP端口,如果在此之前进行了SO_REUSEADDR的设置

	int one = 1;
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))

In this case, every incoming multicast or broadcast UDP datagram destined to the shared port is delivered to all sockets bound to the port.  这种情况下,绑定在该端口上的所有socket都可以收到发往该端口的组播和广播UDP报文

For backwards compatibility reasons, THIS DOES NOT APPLY TO INCOMING UNICAST DATAGRAMS -- unicast datagrams are never delivered to more than one socket, regardless of how many sockets are bound to the datagram's destination port.
为了向后兼容,上述理论并不适用于incoming单播udp数据报, 单播UDP绝对不会被发往多个scoket,只能发往一个socket, 无论多少个socket绑定在了同一个目标端口上
http://www.cnblogs.com/my_life/articles/4397672.html

SO_REUSEADDR可以用在以下四种情况下。 
    (摘自《Unix网络编程》卷一,即UNPv1) 
    1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。 
    2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。 
    3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。 
    4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播/组播,不用于TCP。

 



SOCK_RAW sockets do not require the SO_REUSEADDR option to share a single IP protocol type. The definitions required for the new, multicast-related socket options are found in <netinet/in.h>. All IP addresses are passed in network byte-order. A final multicast-related extension is independent of IP: two new ioctls, SIOCADDMULTI and SIOCDELMULTI, are available to add or delete link-level (e.g., Ethernet) multicast addresses accepted by a particular interface. The address to be added or deleted is passed as a sockaddr structure of family AF_UNSPEC, within the standard ifreq structure.
These ioctls are for the use of protocols other than IP, and require superuser privileges. 这两个ioctls不是给IP协议使用的

A link-level multicast address added via SIOCADDMULTI is not automaticallydeleted when the socket used to add it goes away; it must be explicitly deleted. It is inadvisable to delete a link-level address that may be in use by IP. (These ioctls already exist in SunOS and Ultrix; they are new to BSD Unix.) Drivers that have been modified to support multicasting also support the IFF_PROMISC and IFF_ALLMULTI interface flags, to the degree possible. The kernel modification required to support Van Jacobson's traceroute program is also included in this release. Examples of usage of the above facilities can be found in the programs accompanying this distribution, such as "ping", "mtest" and "rwhod".

 

 

5. ESTABLISHING A DEFAULT MULTICAST INTERFACE 设置默认的组播网卡

Selection of the default multicast interface is controlled via the kernel (unicast) routing table.  If there is no multicast route in the table, all multicasts will, by default, be sent on the interface associated with the
default gateway.  组播默认的网卡的选择是由路由表控制的。如果路由表中没有组播路由表,所有的组播默认会被发往默认网关所绑定的网卡

 

If that interface does not support multicast, attempts to send will receive an ENETUNREACH error. //如果网卡不支持组播,返回ENETUNREACH错误 A route may be added for a particular multicast address or for all multicast addresses, to direct them to a different default interface.

For example, to specify that multicast datagrams addressed to 224.0.1.3 should, by default, be sent on the interface with local address 36.2.0.8,

use the following: /etc/route add 224.0.1.3 36.2.0.8 0    //指定某个特定的组播地址所使用的网卡

 

To set the default for all multicast addresses, other than those with individual routes, to be the interface with local address 36.11.0.1,

use: /etc/route add 224.0.0.0 36.11.0.1 0              //为所有的组播地址指定所使用的网卡

If you point a multicast route at an interface that does not support multicasting, an attempt to multicast via that route will receive an ENETUNREACH error.

 

 

If needed, these commands normally would be added to the /etc/rc.ip or /etc/rc.local file, to take effect every time the system is booted. 9. MTEST The mtest directory contains a small program for testing the multicast membership sockopts and ioctls. It accepts the following commands, interactively: j g.g.g.g i.i.i.i - join IP multicast group l g.g.g.g i.i.i.i - leave IP multicast group a ifname e.e.e.e.e.e - add ether multicast address d ifname e.e.e.e.e.e - del ether multicast address m ifname 1/0 - set/clear ether allmulti flag p ifname 1/0 - set/clear ether promisc flag q - quit where g.g.g.g is an IP multicast address, e.g., 224.0.2.1 i.i.i.i is the IP address of a local interface or 0.0.0.0 ifname is an interface name, e.g., qe0 e.e.e.e.e.e is an Ethernet address in hex, e.g., 1.0.5e.0.2.1 1/0 is a 1 or a 0, to turn the flag on or off The "p" command to change the promiscuous flag does not work under SunOS, because it uses a different ioctl for that purpose. Mtest is useful for establishing targets for multicast ping testing. The results of mtest filter manipulation can be seen by using the "netstat -nia" command (see next section).