2014-12-04 15 views
6

Ho un'implementazione server in cui ho bisogno di 2 socket separati - 1 socket socket IPv4 in ascolto su un particolare indirizzo IPv4 e porta server X e un socket IPv6 in ascolto su un particolare indirizzo IPv6 e sulla stessa porta server X. Gli indirizzi IPv4 e IPv6 si trovano sulla stessa interfaccia.Errore di binding IPv6

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

Sto utilizzando evconnlistener_new_bind per creare socket IPv4 e associarvi. Per il listener IPv6, il codice è il seguente.

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)) 

Come mi legano la mia fd al particolare indirizzo IPv6, vedo un fallimento si legano in modo intermittente.

legano v6 fallita 3ffe sin6 :: A00: 513 - errno 99 - Impossibile assegnare l'indirizzo richiesto

ho cercato di gdb in, ma ogni volta che GDB in, l'associazione ha esito positivo.

Non sono sicuro del motivo per cui sto riscontrando questo problema. Qualcuno può aiutarmi per favore?

+0

Addreses in '3ffe ::/16' non sono validi. Utilizzare invece un indirizzo IPv6 valido. –

+0

La mia interfaccia ha un indirizzo 3ffe :: 10.1.14.14/120. Durante la creazione del socket, la maschera del prefisso non ha alcuna conseguenza? E perché dici che è un indirizzo non valido? – shrejal

+0

Perché non è valido. Quel netblock era obsoleto anni fa. E il fatto che sia in uso indica che qualcosa è orribilmente sbagliato nella configurazione di IPv6. Risolvi prima questo. –

risposta

0

Per impostazione predefinita, dopo che un socket è collegato a una porta TCP, la porta rimane riservata per un minuto quando il socket è chiuso - questo è chiamato lo stato TCP TIME_WAIT. TIME_WAIT evita alcune condizioni di gara che potrebbero causare il danneggiamento dei dati, ma di solito è sicuro ignorare TIME_WAIT sul lato server.

Questo viene fatto impostando l'opzione SO_REUSEADDR presa:

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

Per clacificare, un socket entra nello stato di "TIME_WAIT' quando l'app proprietaria chiude attivamente il socket mentre ha una connessione stabilita (se il peer remoto avvia la chiusura, il socket non inserirà' TIME_WAIT'). È quindi possibile abilitare 'SO_REUSEADDR' sul socket NEXT che si desidera associare alla porta ip + precedentemente associata. –