我正在構建覆蓋網絡系統來測試協議(Uni研究)。我需要加入和離開多播組才能接收來自不同來源的數據包。多播組Linux - 加入和離開
我不確定插座的正確的設置,所以我可以關閉套接字,離開組播組,然後歸隊以後同一個組播組。當我嘗試加入同一組播組時,我會收到「bind error: Address already in use
」。
//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;
}
這是我用於加入羣組的功能。 當離開我簡單地做:(出現這種情況的另一個函數內部)
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多歲的時間間隔內做這個。
非常感謝 中號
問題解決了。 第一次創建組時使用SO_REUSEADDR並使用DROP_MEMBERSHIP可以做到這一點。我不確定哪一個做了實際的修復,因爲我意識到在一種情況下我沒有看到DROP_MEMBERSHIP,無論哪種方式,我都認爲總是在處理多播時設置SO_REUSEADDR是一種很好的做法。 乾杯,M – unixsnob 2012-04-01 17:44:05
@ unixsnob:你很好的解決了你自己。你可以把它當作你的答案。Offtopic:請在代碼中使註釋無效 - 這真的很簡單:例如//釋放結構沒有價值。 – Jayan 2012-04-02 11:35:33