2011-10-03 34 views
17

Tengo un programa que consta de un servidor maestro y servidores esclavos distribuidos. Los servidores esclavos envían actualizaciones de estado al servidor, y si el servidor no ha tenido noticias de un esclavo específico en un período fijo, marca al esclavo como inactivo. Esto está sucediendo consistentemente.No se puede asignar la dirección solicitada: ¿causas posibles?

Al inspeccionar los registros, he encontrado que el esclavo solo puede enviar una actualización de estado al servidor, y nunca puede enviar otra actualización, siempre fallando en la llamada de connect() "No se puede asignar la dirección solicitada (99).

Por extraño que parezca, el esclavo puede enviar varias otras actualizaciones al servidor, y todas las conexiones están sucediendo en el mismo puerto. Parece que la causa más común de esta falla es que las conexiones son dejado abierto, pero estoy teniendo problemas para encontrar algo que quede abierto. ¿Hay otras posibles explicaciones?

Para aclarar, así es como me estoy conectando:

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

Este código está en una función para obtener una conexión a otro servidor, y una falla en cualquiera de esas 4 llamadas hace que la función falle.

+0

He verificado que el puerto y la dirección IP son correctos. – dbeer

Respuesta

9

Quizás SO_REUSEADDR ayude aquí? http://www.unixguide.net/network/socketfaq/4.5.shtml

+0

SO_REUSEADDR está configurado para todas las conexiones. – dbeer

+1

aquí hay uno similar: http://stackoverflow.com/questions/3886506/why-would-connect-give-eaddrnotavail – dmh2000

+0

@ dmh2000 - Miré ese ejemplo antes de publicarlo y no he tenido éxito tratando de analizar esos factores. Me pregunto si solo tengo que seguir buscando o si hay algo que no estoy teniendo en cuenta. – dbeer

3

esto es sólo un tiro en la oscuridad: cuando se llama a conectarse sin un aprieto en primer lugar, el sistema asigna el puerto local, y si usted tiene múltiples hilos de conexión y desconexión que podría tratar de asignar un puerto que ya están en utilizar. el archivo fuente del kernel inet_connection_sock.c alude a esta condición. de la misma manera que en un experimento, intente realizar un enlace a un puerto local primero, asegurándose de que cada enlace/conexión utiliza un número de puerto local diferente.

+0

Voy a intentar esto y ver si ayuda – dbeer

+0

Lo siento, no estaba mirando mi código cuando publiqué eso.Llamo un enlace antes de conectar. Actualizaré mi pregunta para mostrar mejor lo que estoy haciendo. – dbeer

5

Resultó que el problema en realidad era que la dirección estaba ocupada; el ajetreo estaba causado por otros problemas en la forma en que manejamos las comunicaciones de red. Tus aportes me han ayudado a resolver esto. Gracias.

EDIT: Para ser específicos, los problemas en el manejo de nuestras comunicaciones de red fueron que estas actualizaciones de estado serían reenviadas constantemente si la primera fallara. Era solo cuestión de tiempo hasta que todos los esclavos distribuidos intentaran enviar su actualización de estado al mismo tiempo, lo que saturaba demasiado nuestra red.

+0

Me encantaría una explicación sobre "ocupado" en caso de que sea la causa del mismo error aquí en mi propio código, ¿quiere decir "el servidor que acepta las conexiones tiene una cola demasiado larga de sockets esperando aceptar() para otra conexión para ser permitido en la cola? "¿O alguna otra circunstancia? ¡Gracias! –

+2

@BrandonRhodes nuestro problema era que teníamos que volver a intentar algo sin un algoritmo de finalización adecuado, por lo que teníamos cientos o más intentos de conexión al mismo socket cada segundo. Esta contención estaba causando nuestro fracaso. La implementación de un algoritmo de retroceso adecuado fue crucial para resolver este problema. – dbeer

+0

¡Gracias por la información adicional! Me alegro de que lo tienes solucionado. –

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

¿cómo deshacer estos 2? – ado

+6

Sin explicación, esta respuesta no tiene ningún valor. –

Cuestiones relacionadas