|
各位好,目前遇到一个2.6内核下的组播问题要请教一下。
环境:
支持IGMPv2和IGMP snooping的交换机,
一台组播服务器使用2.4.20内核,Redhat9
一台PC客户端使用2.6.8内核,Fedora core 3
服务器和客户端上运行后面给出的组播示例程序,程序从网上找的,编译都没有问题。
症状:
客户端无法接收服务器下来的组播数据,经过调查认为是Fedora core 3目前支持的是IGMPv3,
由于交换机不支持IGMPv3,所以加入组播组的消息被忽略,这点通过在客户端上运行iptraf可以
看到,发送的消息是到IGMPv3的224.0.0.22而不是IGMPv2里面的224.0.0.2。
基于此,根据网上查阅的信息,强制让Fedora core 3使用IGMPv2,
#/sbin/sysctl -w net.ipv4.conf.eth1.force_igmp_version=2
重新运行客户端组播接收程序和iptraf,现在发现确实申请加入组播地址224.0.0.2,
而且在iptraf里也看到了组播服务器下来的组播数据,但是客户端的程序却无法接收上来。
分析:
iptraf可以看到组播服务器下来的数据说明强制让Fedora core 3使用IGMPv2发生了效果,
但是为何客户端应用层上还是无法接收呢?
此问题已经困扰我好几天了,不知道版上有没有专家可以解答?非常感谢!
/*
multicast.c
The following program sends or receives multicast packets. If invoked
with one argument, it sends a packet containing the current time to an
arbitrarily chosen multicast group and UDP port. If invoked with no
arguments, it receives and prints these packets. Start it as a sender on
just one host and as a receiver on all the other hosts
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#define EXAMPLE_PORT 6000
#define EXAMPLE_GROUP "239.0.0.1"
main(int argc)
{
struct sockaddr_in addr;
int addrlen, sock, cnt;
struct ip_mreq mreq;
char message[50];
/* set up socket */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
bzero((char *)&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(EXAMPLE_PORT);
addrlen = sizeof(addr);
if (argc > 1) {
/* send */
addr.sin_addr.s_addr = inet_addr(EXAMPLE_GROUP);
while (1) {
time_t t = time(0);
sprintf(message, "time is %-24.24s", ctime(&t));
printf("sending: %s\n", message);
cnt = sendto(sock, message, sizeof(message), 0,
(struct sockaddr *) &addr, addrlen);
if (cnt < 0) {
perror("sendto");
exit(1);
}
sleep(5);
}
} else {
/* receive */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
mreq.imr_multiaddr.s_addr = inet_addr(EXAMPLE_GROUP);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq)) < 0) {
perror("setsockopt mreq");
exit(1);
}
while (1) {
cnt = recvfrom(sock, message, sizeof(message), 0,
(struct sockaddr *) &addr, &addrlen);
if (cnt < 0) {
perror("recvfrom");
exit(1);
} else if (cnt == 0) {
break;
}
printf("%s: message = \"%s\"\n", inet_ntoa(addr.sin_addr), message);
}
}
} |
|