2011-10-03 11 views
17

Ho un programma che consiste in un server master e server slave distribuiti. I server slave inviano aggiornamenti di stato al server e, se il server non ha ricevuto notizie da uno specifico slave in un determinato periodo, contrassegna lo slave come inattivo. Questo sta accadendo in modo coerente.Impossibile assegnare l'indirizzo richiesto - possibili cause?

Dall'analisi dei registri, ho rilevato che lo slave è in grado di inviare solo un aggiornamento di stato al server e quindi non è mai in grado di inviare un altro aggiornamento, sempre in mancanza della chiamata per connettersi() "Impossibile assegnare l'indirizzo richiesto (99)

Stranamente, lo slave è in grado di inviare diversi altri aggiornamenti al server e tutte le connessioni si verificano sulla stessa porta. Sembra che la causa più comune di questo errore sia che le connessioni sono lasciato aperto, ma ho difficoltà a trovare qualcosa lasciato aperto Ci sono altre possibili spiegazioni?

Per chiarire, ecco come mi sto connettendo:

struct sockaddr *sa; // parameter 
size_t   sa_size; //parameter 
int    i = 1; 
int    stream; 

stream = socket(AF_INET,SOCK_STREAM,0); 
setsockopt(stream,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i)); 
bindresvport(stream,NULL); 
connect(stream,sa,sa_size); 

Questo codice è in una funzione per ottenere una connessione a un altro server e un errore in una di queste 4 chiamate causa la mancata riuscita della funzione.

+0

Ho verificato che la porta e l'indirizzo IP sono entrambi corretti. – dbeer

risposta

9
+0

SO_REUSEADDR è impostato per tutte le connessioni. – dbeer

+1

eccone uno simile: http://stackoverflow.com/questions/3886506/why-would-connect-give-eaddrnotavail – dmh2000

+0

@ dmh2000 - Ho guardato quell'esempio prima di postare e non ho avuto successo nel cercare di esaminare quei fattori. Mi chiedo se devo solo continuare a cercare o se c'è qualcosa che non sto prendendo in considerazione. – dbeer

3

questo è solo un salto nel buio: quando si chiama connettersi senza un vicolo cieco prima, il sistema assegna la porta locale e se si dispone di più thread di collegare e scollegare forse potrebbe cercare di allocare già in un porto uso. il file sorgente del kernel inet_connection_sock.c suggerisce questa condizione. proprio come un esperimento, provare prima a collegarsi a una porta locale, assicurandosi che ogni collegamento/connessione utilizzi un numero di porta locale diverso.

+0

Proverò questo e vedrò se aiuta – dbeer

+0

Scusa, non stavo guardando il mio codice quando l'ho postato.Io chiamo un binding prima di connetterti. Aggiornerò la mia domanda per mostrare meglio quello che sto facendo. – dbeer

5

Si è scoperto che il problema era che l'indirizzo era occupato: l'attività era causata da altri problemi nel modo in cui gestiamo le comunicazioni di rete. I tuoi input mi hanno aiutato a capirlo. Grazie.

MODIFICA: per essere specifici, i problemi nella gestione delle nostre comunicazioni di rete erano che questi aggiornamenti di stato sarebbero costantemente re-inviati se il primo non era riuscito. Era solo una questione di tempo prima che tutti gli slave distribuiti provassero a inviare il suo aggiornamento di stato nello stesso momento, il che stava saturando la nostra rete.

+0

Mi piacerebbe un'elaborazione su "occupato" nel caso in cui sia la causa dello stesso errore qui nel mio codice - intendi "il server che accetta le connessioni ha avuto troppo tempo una coda di socket in attesa di accept() per un'altra connessione essere ammessi in coda? "O un'altra circostanza? Grazie! –

+2

@BrandonRhodes il nostro problema era che avevamo un nuovo tentativo senza un adeguato algoritmo di backoff, quindi abbiamo avuto centinaia o più tentativi di connessione allo stesso socket ogni secondo. Questa contesa stava causando il nostro fallimento. L'implementazione di un adeguato algoritmo di backoff è stato fondamentale per risolvere questo problema. – dbeer

+0

Grazie per le informazioni aggiuntive! Sono contento di averlo sistemato. –

1
sysctl -w net.ipv4.tcp_timestamps=1 
sysctl -w net.ipv4.tcp_tw_recycle=1 
+3

come si annullano questi 2? – ado

+6

Senza spiegazione questa risposta non ha alcun valore. –

Problemi correlati