| Ver tema anterior :: Ver siguiente tema | | Autor | Mensaje |
|---|
anacara
Registrado: 20 Mar 2007 Mensajes: 3
| Publicado: 20/03/2007 1:24 pm | | | Título: Problemas con las hebras al desconectar un cliente |
| Hola!
Tengo un servidor de chat en C++ que trabaja sobre Linux al cual se conectan una serie de clientes por medio de sockets.
Para atender a cada cliente se crea una hebra lectora y otra escritora y todas las hebras del servidor se comunican por medio de un fichero en el que se van escribiendo mensajes (tanto mensajes de usuario como para informar de nuevos conectados y desconectados). Dicho fichero se protege con un monitor de acceso, siguiendo un esquema lector-escritor y cada vez que un escritor anota un nuevo mensaje se envía una señal a todos las hebras que se encuentran bloqueados en una cola (uso la función pthread_cond_broadcast de pthread.h).
Durante la ejecución normal (recibir nuevas conexiones y mensajes de los clientes e informar de ellas al resto de usuarios) todo funciona bien, pero tengo problemas para desconectar clientes e informar al resto.
Cuando se recibe una solicitud de desconexión, se anota un mensaje en el fichero, se cierran los sockets y se finalizan las hebras asociadas al cliente que se ha desconectado. El problema es que sólo uno o dos de las otras hebras se despierta y accede al fichero, el resto permanecen bloquedas, por lo que los clientes no se enteran de la desconexión.
Buscando el motivo del problema he observado lo siguiente: 1. Si no cierro el socket de la hebra lectora y no la finalizo (la dejo en un bucle infinito sin hacer nada) todo funciona a la perfección.
2. Si cierro el socket y mato la hebra el resto de hebras no lee el fichero hasta que se produce una nueva conexión (que, en general, suele recuperar el socket cerrado por la hebra que murió).
Para cerrar el socket simplemente hago close(idSocket).
¿Alguien puede ayudarme? |
| | Volver arriba | |  | quique
Registrado: 30 Mar 2004 Mensajes: 720 Ubicación: Por ahí
| Publicado: 23/03/2007 4:52 am | | | Título: |
| No pongas el mismo mensaje en mas de un foro a la vez.
Leete las normas de los foros _________________ /* no comment */ |
| | Volver arriba | |  | ciomar
Registrado: 01 Abr 2007 Mensajes: 5
| Publicado: 01/04/2007 6:49 pm | | | Título: Re: Problemas con las hebras al desconectar un cliente |
| | anacara escribió: | Hola!
Tengo un servidor de chat en C++ que trabaja sobre Linux al cual se conectan una serie de clientes por medio de sockets.
Para atender a cada cliente se crea una hebra lectora y otra escritora y todas las hebras del servidor se comunican por medio de un fichero en el que se van escribiendo mensajes (tanto mensajes de usuario como para informar de nuevos conectados y desconectados). Dicho fichero se protege con un monitor de acceso, siguiendo un esquema lector-escritor y cada vez que un escritor anota un nuevo mensaje se envía una señal a todos las hebras que se encuentran bloqueados en una cola (uso la función pthread_cond_broadcast de pthread.h).
Durante la ejecución normal (recibir nuevas conexiones y mensajes de los clientes e informar de ellas al resto de usuarios) todo funciona bien, pero tengo problemas para desconectar clientes e informar al resto.
Cuando se recibe una solicitud de desconexión, se anota un mensaje en el fichero, se cierran los sockets y se finalizan las hebras asociadas al cliente que se ha desconectado. El problema es que sólo uno o dos de las otras hebras se despierta y accede al fichero, el resto permanecen bloquedas, por lo que los clientes no se enteran de la desconexión.
Buscando el motivo del problema he observado lo siguiente: 1. Si no cierro el socket de la hebra lectora y no la finalizo (la dejo en un bucle infinito sin hacer nada) todo funciona a la perfección.
2. Si cierro el socket y mato la hebra el resto de hebras no lee el fichero hasta que se produce una nueva conexión (que, en general, suele recuperar el socket cerrado por la hebra que murió).
Para cerrar el socket simplemente hago close(idSocket).
¿Alguien puede ayudarme? |
Si se cierra el socket, el socket no deja de existir. Dependiendo de lo que estuviera haciendo el cliente/servidor, se pone en el estado "TIME_WAIT", lo cual no libera los recursos del proceso correspondientes al file_descriptor asignado en este caso al socket (vease maquina de estado de TCP). Este motivo puede ser por el cual no se dan cuenta el resto de los threads de que se cerro el socket. Si queres ver el estado de los sockets en en sistema, utilizá la intruccion "netstat -n". Te recomiendo que realices un esquema mas de pase de mensajes, y sincronices todo con la funcion "select()" a la hora de acceder al archivo de mensajes. Inclusive te recomendaría que utilices la misma funcion para lectura/escritura en los threads, ya que estas disparando muchos hilos por proceso. Si deseas realizar una sincronización un poco mas pareja, te recomiendo que utilices la bilbioteca de semáforos de hilos (semaphore.h), ya que los monitores no te permiten sicronizar mas de 2 hilos simultáneamente (en tu caso lectura/escritura). El motivo que se te cuelgue con el monitor, puede deberse a que los 2 hilos (escritura/lectura) generen un "deadlock" en el monitor, no permitiendo que ninguna otra hebra entre en el monitor. Ojo con la cantidad de file descriptor habiertos, ya que cada hilo utiliza la misma tabla de filedescriptors de todo el proceso. No te sorprendas si al abrir mas de 255 sockets simultánemente, no puedas realizar mas connects o accepts. Para el archivo, te recomiendo que utilices mmap() para leer escribir el archivo, y si te quedas corto con los file descriptors, realizá algunos fork() con multihilos adentro, y hace un mapeo de memoria (mmap) con "shared memory" para que se vean las modificaciones entre los procesos...
Salu2 y suerte... |
| | Volver arriba | |  | | |
| No puede crear mensajes No puede responder temas No puede editar sus mensajes No puede borrar sus mensajes No puede votar en encuestas
|
|
| |