红联Linux门户
Linux帮助

Linux 组播问题 收发

发布时间:2010-02-02 15:26:12来源:红联作者:yarges
发送端代码:
if(IPv6 && (sfd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) <0){
log_sys_err("Unable to create IPv6 socket");
error = -errno;
goto fail;
}

if(!IPv6 && ((sfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)){
log_sys_err("Unable to create socket for broadcast");
error = -errno;
goto fail;
}

memset(&addr, 0, sizeof(struct sockaddr_storage));

trueint = 1;
if(IPv6){
struct ipv6_mreq mreq;

addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(backend_port);

if(!multicast_address || !strcmp(multicast_address, "default")){
log_dbg("Trying IPv6 multicast (default).\n");
if(inet_pton(AF_INET6, "ff02::3:1", &(addr6->sin6_addr)) <= 0){
log_sys_err("Unable to convert multicast address");
error = -errno;
goto fail;
}
} else {
log_dbg("Trying IPv6 multicast (%s).\n", multicast_address);
if(inet_pton(AF_INET6, multicast_address, &(addr6->sin6_addr)) <= 0){
log_sys_err("Unable to convert multicast address");
error = -errno;
goto fail;
}
}

memcpy(&mreq.ipv6mr_multiaddr, &(addr6->sin6_addr), sizeof(struct in6_addr));
mreq.ipv6mr_interface = 0;
opt = 0;

if(setsockopt(sfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
&opt, sizeof(opt)) < 0){
log_err("Unable to %s loopback.\n", opt?"SET":"UNSET");
error = -errno;
goto fail;
}
} else {
addr4->sin_family = AF_INET;
addr4->sin_port = htons(backend_port);
if(!multicast_address){
log_dbg("Trying IPv4 broadcast.\n");

addr4->sin_addr.s_addr = INADDR_BROADCAST;
if((error = setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, &trueint, sizeof(int)))){
log_sys_err("Unable to set socket options");
error = -errno;
goto fail;
} else {
log_dbg(" Broadcast enabled.\n");
}
} else {
if(!strcmp(multicast_address, "default")){
log_dbg("Trying IPv4 multicast (default).\n");
if(inet_pton(AF_INET, "224.0.2.5", &(addr4->sin_addr)) <= 0){
log_sys_err("Unable to convert multicast address");
error = -errno;
goto fail;
}
} else {
log_dbg("Trying IPv4 multicast (%s).\n", multicast_address);
if(inet_pton(AF_INET, multicast_address, &(addr4->sin_addr)) <= 0){
log_sys_err("Unable to convert multicast address");
error = -errno;
goto fail;
}
}
opt = 0;
setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_LOOP, &opt, sizeof(opt));
if(setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0){
log_sys_err("Unable to set multicast threshold.\n");
}
}
}
addr_size = IPv6? sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in);


接收端代码:
sfd = socket((IPv6)? PF_INET6: PF_INET, SOCK_DGRAM, 0);
if(sfd < 0){
log_sys_err("Socket creation failed");
exit(EXIT_FAILURE);
} else {
int trueint = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &trueint, sizeof(int))){
log_sys_err("Unable to set socket option");
exit(EXIT_FAILURE);
}
}

if(IPv6){
addr_size = sizeof(struct sockaddr_in6);
addr6->sin6_family = AF_INET6;
addr6->sin6_addr = in6addr_any;
addr6->sin6_port = htons(backend_port);
} else {
addr_size = sizeof(struct sockaddr_in);
addr4->sin_family = AF_INET;
addr4->sin_addr.s_addr = INADDR_ANY;
addr4->sin_port = htons(backend_port);
}

if(bind(sfd, (struct sockaddr *)&addr, addr_size) < 0){
log_sys_err("1636 Unable to bind socket");
close(sfd);
return -errno;
}

if(IPv6 || multicast_address){
if(join_group(sfd, 1, backend_port)){
log_err("Unable to join multicast group.\n");
exit(EXIT_FAILURE);
}
}
其中join_group(sfd, 1, backend_port)函数如下

int join_group(int sfd, int loopback, int port){
int error = 0;
char *addr_string;
struct sockaddr_storage addr;
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;

ENTER("join_group");

if(IPv6){
if(!multicast_address || !strcmp("default", multicast_address)){
addr_string = "ff02::3:1";
} else {
addr_string = multicast_address;
}
inet_pton(AF_INET6, addr_string, &(addr6->sin6_addr));
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(port);
} else {
if(!strcmp("default", multicast_address)){
addr_string = "224.0.2.5";
} else {
addr_string = multicast_address;
}
inet_pton(AF_INET, addr_string, &(addr4->sin_addr));
addr4->sin_family = AF_INET;
addr4->sin_port = htons(port);
}

if(addr.ss_family == AF_INET){
struct ip_mreq mreq;

mreq.imr_multiaddr.s_addr = addr4->sin_addr.s_addr;
mreq.imr_interface.s_addr = INADDR_ANY;

if(setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_LOOP,
&loopback, sizeof(loopback)) < 0){
log_err("Unable to %s loopback.\n", loopback?"SET":"UNSET");
error = -errno;
goto fail;
}
if(setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(const void *)&mreq, sizeof(mreq)) < 0){
log_err("Unable to add to membership.\n");
error = -errno;
goto fail;
}
} else if(addr.ss_family == AF_INET6){
struct ipv6_mreq mreq;

memcpy(&mreq.ipv6mr_multiaddr, &(addr6->sin6_addr), sizeof(struct in6_addr));

mreq.ipv6mr_interface = 0;

if(setsockopt(sfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
&loopback, sizeof(loopback)) < 0){
log_err("Unable to %s loopback.\n", loopback?"SET":"UNSET");
error = -errno;
goto fail;
}
if(setsockopt(sfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(const void *)&mreq, sizeof(mreq)) < 0){
log_err("Unable to add to membership: %s\n", strerror(errno));
error = -errno;
goto fail;
}
} else {
log_err("Unknown address family.\n");
error = -EINVAL;
}
fail:
EXIT("join_group");
return 0;
}

出现问题:有时就回接不到消息,为什么 请高手指点啊谢谢
文章评论

共有 2 条评论

  1. yarges 于 2010-02-04 10:30:20发表:

    问题找到了 是 ipv4和ipv6的操作问题

  2. zhangyinghao452 于 2010-02-03 20:42:03发表:

    也没看出问题来,同样等高手,可不可以截一下包看看是收还是发端的问题?