首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >组播组Linux -加入和离开

组播组Linux -加入和离开
EN

Stack Overflow用户
提问于 2012-04-02 00:54:08
回答 1查看 4K关注 0票数 0

我正在构建一个覆盖网络系统来测试一个协议(Uni研究)。为了接收来自不同来源的数据包,我需要加入和离开多播组。

我不确定套接字的正确设置,因此我可以关闭套接字并离开多播组,然后稍后重新加入同一多播组。当我尝试加入同一个多播组时,我得到了"bind error: Address already in use“。

代码语言:javascript
复制
//for setting up individual groups
int setUpForGroup(struct locgro_node* node, const char* port)
{
    char mcastaddr[INET6_ADDRSTRLEN];

    struct in6_addr* full_addr_gro = &(node->group);
    if( NULL == inet_ntop(AF_INET6, full_addr_gro, mcastaddr, INET6_ADDRSTRLEN))
    {   
        printf("error inet_pton, retval: \n");
        return -1;
    }

    if (buildAdd(mcastaddr, port, AF_INET6, SOCK_DGRAM, &(node->addr_st)) <0) 
    {
        fprintf(stderr, "get_addr error:: could not find multicast, address=[%s] port=[%s]\n", mcastaddr, port);
        return -1;
    }

    node->sockfd = socket(AF_INET6, SOCK_DGRAM, 0);

    if (bind(node->sockfd, (struct sockaddr *)&(node->addr_st), sizeof(node->addr_st)) < 0) {
        perror("bind error:: ");
        close(node->sockfd);
        return -1;
    }

    if (joinGroup(node->sockfd, 0 , 8, &(node->addr_st)) <0) {
        close(node->sockfd);
        return -1;
    }

    return 0;
}
//internal function
int joinGroup(int sockfd, int loopBack, int mcastTTL, struct sockaddr_in6 *addr_st)
{
    int r1, r2, r3, retval;
    retval=-1;
    struct ipv6_mreq mreq6;

    memcpy(&mreq6.ipv6mr_multiaddr, &((addr_st)->sin6_addr), sizeof(struct in6_addr));

    mreq6.ipv6mr_interface= 0; // allow any interface

    //set the loopback case
    r1 = setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loopBack, sizeof(loopBack));
    if (r1<0) perror("joinGroup:: IPV6_MULTICAST_LOOP:: ");

/*
    setsockopt(sock_fd, IPPROTO_IPV6, SO_REUSEADDR, &mreq6, sizeof(mreq6));

    setsockopt(sock_fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &multicast_req, sizeof(multicast_req));
*/
    //set the time to live for the packets (hops)
    r2 = setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL));
    if (r2<0) perror("joinGroup:: IPV6_MULTICAST_HOPS::  ");

    //add this address to the group
    r3 = setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6));
    if (r3<0) perror("joinGroup:: IPV6_ADD_MEMBERSHIP:: ");

    if ((r1>=0) && (r2>=0) && (r3>=0)) retval=0;

    return retval;
}


//internal function
int buildAdd(const char *hostname, const char *service, int family, int socktype,  struct sockaddr_in6 *addr_st)
{
    struct addrinfo hints, *res, *ressave;
    int n, sockfd, retval;

    retval = -1;

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = family;
    hints.ai_socktype = socktype;

    n = getaddrinfo(hostname, service, &hints, &res);

    if (n <0) 
    {
        fprintf(stderr, "getaddrinfo error: [%s]\n", gai_strerror(n));
        return retval;
    }

    ressave = res;

    sockfd=-1;
    while(res) 
    {
        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

        if (!(sockfd < 0)) 
        {
            int opval = 1;
            setsockopt(sockfd, IPPROTO_IPV6, SO_REUSEADDR, &opval, res->ai_addrlen);

            if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0) 
            {
            //to test that the address really is correct
                close(sockfd);
                memcpy(addr_st, res->ai_addr, sizeof(*addr_st));
                retval=0;
                break;
            }
            perror("build addr : bind error");
            close(sockfd);
            sockfd=-1;
        }
        res=res->ai_next;
    }

    freeaddrinfo(ressave); //free the struct

    return retval;
}

这些是我用来加入群组的函数。当我离开时,我只是这样做:(这发生在另一个函数中)

代码语言:javascript
复制
    struct ipv6_mreq mreq6;
    memcpy(&mreq6.ipv6mr_multiaddr, &(temp_lnode->group), sizeof(struct in6_addr));
    mreq6.ipv6mr_interface= 0; // allow any interface
    setsockopt(temp_lnode->sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6));

    close(temp_lnode->sockfd); //close socket

当我试图在构建地址函数中绑定地址时,我得到了一个“地址已经在使用中”的错误。我试着通过设置SO_REUSEADDR来解决这个问题,但是没有帮助,我还添加了DROP_MEMBERSHIP,但是绑定仍然失败。

我需要绑定才能让它工作吗?我应该调用或做什么才能允许没有此问题的组的加入和离开?我需要在30秒的间隔内这样做。

非常感谢我

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-06-18 22:48:08

问题解决了。在第一次创建组时使用SO_REUSEADDR并使用DROP_MEMBERSHIP可以完成此任务。我不确定哪一个做了实际的修复,因为我意识到我在一个案例中没有看到DROP_MEMBERSHIP,无论哪种方式,我读到在处理多播时总是设置SO_REUSEADDR是一个很好的做法。干杯,M

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9966258

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档