2014-12-04 27 views
6

Mam wdrożenie serwera, w którym potrzebuję 2 oddzielne gniazda - 1 gniazdo gniazda IPv4 nasłuchujące na określonym adresie IPv4 i porcie serwera X oraz gniazdo IPv6 nasłuchujące na określonym adresie IPv6 i tym samym porcie serwera X. Adresy IPv4 i IPv6 znajdują się w tym samym interfejsie.Niepowodzenia wiązania IPv6

memset(&sin, 0, sizeof(sin)); 
    sin.sin_family  = AF_INET; 
    sin.sin_addr.s_addr = htonl(v4addr); 
    sin.sin_port  = htons(tcp_port); 

Używam evconnlistener_new_bind do utworzenia gniazda ipv4 i powiązania go. Dla detektora IPv6 kod jest następujący.

memset(&sin6, 0, sizeof(sin6)); 
    sin6.sin6_family  = AF_INET6; 
    memcpy(sin6.sin6_addr.s6_addr, v6addr_bytes, IPV6_ADDR_LEN); 
    sin6.sin6_port  = htons(tcp_port); 

    fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 
    evutil_make_socket_nonblocking(fd) 
    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on)) 
    setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&on, sizeof(on)) 
    evutil_make_listen_socket_reuseable(fd) /* Libevent call to set SO_REUSEADDR */ 
    evutil_make_socket_nonblocking(fd)  /* Libevent call to set fd non-blocking */ 
    bind(fd, (const struct sockaddr *)&sin6, sizeof(sin6)) 

Ponieważ wiążę mój fd z konkretnym adresem ipv6, widzę sporadycznie błąd wiązania.

wiążą v6 udało 3ffe sin6 :: A00: 513 - errno 99 - Nie można przypisać żądany adres

Próbowałem w gdb, ale za każdym razem gdb się w, wiążą się powiedzie.

Nie jestem pewien, dlaczego widzę ten problem. Czy ktoś może Ci pomóc?

+0

Addreses w '3ffe ::/16' nie są ważne. Zamiast tego użyj poprawnego adresu IPv6. –

+0

Mój interfejs ma adres 3ffe :: 10.1.14.14/120. Podczas tworzenia gniazda maska ​​prefiksu nie ma żadnych konsekwencji? I dlaczego mówisz, że jest to nieprawidłowy adres? – shrejal

+0

Ponieważ jest nieważny. Ten netblock był przestarzały lata temu. A fakt, że jest on w ogóle używany, wskazuje, że coś jest nie tak z konfiguracją IPv6. Najpierw to załatw. –

Odpowiedz

0

Domyślnie, po podłączeniu gniazda do portu TCP, port pozostaje zarezerwowany na jedną minutę, gdy gniazdo jest zamknięte - nazywane jest to stanem TCP TIME_WAIT. TIME_WAIT omija niektóre warunki wyścigu, które mogą powodować uszkodzenie danych, ale zwykle można bezpiecznie zignorować po stronie serwera TIME_WAIT.

Odbywa się to poprzez ustawienie opcji SO_REUSEADDR gniazda:

int one = 1; 
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) 
+1

Aby wyczyścić, gniazdo wchodzi w stan 'TIME_WAIT', gdy aplikacja będąca aktywnym zamknie gniazdo, gdy ma ustanowione połączenie (jeśli zdalny peer zainicjuje zamknięcie, to gniazdo nie wejdzie w' TIME_WAIT'). Następnie możesz włączyć opcję 'SO_REUSEADDR' na gnieździe NEXT, które chcesz powiązać z wcześniej powiązanym portem ip +. –

Powiązane problemy