Foros del Web » Programación para mayores de 30 ;) » Java »

Escribir al mismo tiempo en el mismo socket

Estas en el tema de Escribir al mismo tiempo en el mismo socket en el foro de Java en Foros del Web. Hola a todos, Acudo a vosotros para pediros ayuda relacionada con el envió de información por el mismo socket de varios hilos. Mi programa está ...
  #1 (permalink)  
Antiguo 09/04/2009, 16:30
 
Fecha de Ingreso: abril-2007
Mensajes: 40
Antigüedad: 17 años, 1 mes
Puntos: 0
Escribir al mismo tiempo en el mismo socket

Hola a todos,

Acudo a vosotros para pediros ayuda relacionada con el envió de información por el mismo socket de varios hilos. Mi programa está formado por:
- un cliente que se conecta con el servidor y crear varios hilos. Cada hilo usa el mismo socket para enviar una petición y se queda esperando su respuesta. Una vez recibida la respuesta los hilos verifican si la respuesta le corresponde (lo puede verificar ya que al enviar la petición, esta es un ArrayList donde el primer elemento es un código único que tiene cada hilo y el segundo es realmente la petición y en la respuesta este código único se incluye). Si la respuesta le corresponde hace cosas y luego vuelve a hacer lo mismo y de lo contrario se queda esperando de nuevo su respuesta (es decir hace un readObject de ObjectInputStream).
- el servidor acepta la conexión del cliente y crear un hilo que se queda a la espera de peticiones (readObject de ObjectInputStream). Por cada petición recibida crea un nuevo hilo pasándole esa petición + el ObjectOutputStream para que pueda devolver el resultado y luego este hilo se muere.

Una vez arrancado el servidor si modifico el cliente para que solo tenga un hilo entonces todo funciona perfectamente, en cambio si dejo que genere varios hilos me peta. Los errores son varios :
A veces me da java.net.SocketException: Software caused connection abort: socket write error
Y otras veces
java.io.EOFException at java.io.ObjectInputStream$BlockDataInputStream.pee kByte(ObjectInputStream.java:2554)

Creo que el problema esta en que se intenta escribir al mismo tiempo en el mismo socket o algo asi.



Gracias de antemano.
  #2 (permalink)  
Antiguo 10/04/2009, 00:02
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 7 meses
Puntos: 454
Respuesta: Escribir al mismo tiempo en el mismo socket

Hola:

Varios hilos no puedes escribir o leer simultáneamente del mismo socket. Imagina que tienes dos hilos que intentan enviar dos mensajes a la vez por el mismo socket. Si los mensajes son suficientemente grandes o tienes la mala suerte, el socket entremezclará los bytes de ambos mensajes y enviará una cosa ilegible al otro lado.

Para manejar un único socket con varios hilos, habría que sincronizarlos.

Código:
synchronized (elSocket) {
   enviarporelsocket o leer del socket.
}
Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #3 (permalink)  
Antiguo 10/04/2009, 01:13
 
Fecha de Ingreso: abril-2007
Mensajes: 40
Antigüedad: 17 años, 1 mes
Puntos: 0
Pregunta Respuesta: Escribir al mismo tiempo en el mismo socket

Hola chuidiang,

Gracias por tu respuesta y por tus contribuciones ya que estoy aprendiendo mucho de ti.
Sobre sincronizar los envios por el socket lo entiendo perfectamente, pero lo que no me queda claro es porque tengo que sincronizar tambien las lecturas.

Es decir que si sincronizo las envios, mi servidor funcionará perfectamente porque solo hay un hilo que lee y por cada lectura hay un hilo que luego escribe y por tanto si aplico tu consejo entonces sincronizo las escrituras y todo ok. El problema esta en que en el cliente tengo varios hilos que escriben pero tambien leen es decir que para mi es importante que todos los hilos del cliente reciban la misma respuesta del servidor y que ellos luego comprueben si es suya o no.

Si es imposible que los hilos del cliente lean simultaneamente la misma respuesta, ¿Crees que lo que hay que hacer es poner la misma arquitectura que la del servidor que consistiria en que tenga un solo hilo que leea y que le pase la respuesta a todos los demas en vez de que ello la esperen? ¿Que me aconsejarias? Tambien queria saber si al escribir en el socket hay que hacer simpre flush.

Gracias de nuevo.
  #4 (permalink)  
Antiguo 10/04/2009, 04:43
 
Fecha de Ingreso: abril-2007
Mensajes: 40
Antigüedad: 17 años, 1 mes
Puntos: 0
Respuesta: Escribir al mismo tiempo en el mismo socket

Otra duda que tengo es si tengo que sincronizar solo el socket o tambien el OutputStream antes de enviar los datos y InputStream antes de recibiros.

Saludos
  #5 (permalink)  
Antiguo 10/04/2009, 04:49
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 7 meses
Puntos: 454
Respuesta: Escribir al mismo tiempo en el mismo socket

Hola:

Un socket tiene internamente dos buffers de bytes, uno para lectura y otro para escritura.

Cuando un hilo escribe, realmente está situando bytes en ese buffer y el sistema operativo se encargará de ir enviando esos bytes por el canal hacia el otro ejecutable. Si varios hilos escriben a la vez, van metiendo entremezclados sus bytes en ese buffer, por eso es necesario sincronizar las escrituras.

En la lectura, el sistema operativo va dejando los bytes que recibe en un buffer de lectura. Cuando un hilo lee, está retirando los bytes del buffer, por lo que otro hilo no va a poder leer lo mismo. Si dos hilos intentan leer a la vez, puede que uno se quede con parte de los bytes y otro con otra parte. Por ello, las lecturas también deben estar sincronizadas.

Los bufferes de escritura y lectura son independientes, por lo que un hilo podría escribir y otro leer a la vez sin sincronización y no habría problemas. Por ello, realmente debes usar para sincronizar los OutputStream para los hilos que escriben y los InputStream para los que leen.

En el caso del cliente, al leer los hilos sincronizadamente, no tienes garantía ninguna de que cada uno lea el mensaje que le corresponde y si lee un mensaje que no es para él, al retiralo del buffer, el otro hilo ya no lo encontrará. No funciona por tanto que varios hilos lean de un mismo socket. En java tienes opciones para "ver" que tiene el buffer de lectura sin retirarlo, por lo que los hilos podrían, sincronizadamente, mirar ese buffer para ver si lo que hay es para él y así retirarlo o no. De todas formas, no suele usarse esta opción, ya que la gestión suele ser compleja.

Lo suyo es hacer un único hilo que extraiga los mensajes del socket y los vaya repartiendo, o bien que cada hilo abra su propio socket con el servidor. Se suele elegir una opción u otra en función de la cantidad de mensajes, cantidad de hilos, si comparten o no muchos mensajes, etc.

- Si hay pocos hilos cliente y el funcionamiento es petición del cliente-respuesta del servidor, es mejor que cada uno abra su propio socket.

- Si hay muchos hilos y van a tener muchos mensajes compartidos y el servidor puede a veces enviar mensajes sin necesidad de que el cliente lo pida, entonces es mejor un único hilo cliente que vaya repartiendo mensajes a los demás.

El motivo de estas decisiones es, por un lado, que no se pueden mantener simultáneamente muchos descriptores de fichero abiertos (sockets), el sistema operativo no lo permite. Si hay muchos hilos (alrededor de 64 o más), el sistema operativo no te permitirá abrir tantos sockets simultáneamente.

Por otro lado, si la relación cliente-servidor es petición-respuesta, es mejor que cada uno tenga su propio socket, ya que así cada hilo sólo recibirá lo que ha pedido. El que "reparte" no tendrá que saber quién ha pedido algo ni pasará mensajes innecesariamente a los hilos que no lo necesitan. Sin embargo, si el servidor puede enviar cosas por su cuenta que pueden interesar a varios hilos, es mejor un único socket, evitando al servidor tener que enviar el mensaje muchas veces por todos los sockets abiertos.

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #6 (permalink)  
Antiguo 10/04/2009, 13:27
 
Fecha de Ingreso: abril-2007
Mensajes: 40
Antigüedad: 17 años, 1 mes
Puntos: 0
De acuerdo Respuesta: Escribir al mismo tiempo en el mismo socket

Gracias chuidiang,

Ahora me ha quedado claro el funcionamiento de los sockets. Así que seguire usando la opción de un único soket ya que puedo tener hasta 80 hilos por cliente conectado y ademas puedo tener muchos clientes y como mi cliente realmente es un applet y lo tendre en una maquina mia entonces tendria que abrir una barbaridad de socket si eligiera la otra opción. Lo único que ahora que lo tengo bastante claro voy a modificar un poco la arquiectura.


Queria hacerte una ultima pregunta relacionada con los applet y sockets. Si en una maquina mia tengo el Applet (cliente) que intenta conectarse a un servidor por un determinado puerto ¿basta con solo abrir el puerto en la maquina donde tengo el applet o tambien lo tiene que abrir el usuario que abre su navegador y ejecuta mi applet en el caso de que tenga un firewall? o mejor dicho ¿el applet desde donde realiza la conexión, desde mi maquina o desde el PC de usuario?

Gracias
  #7 (permalink)  
Antiguo 11/04/2009, 00:00
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 7 meses
Puntos: 454
Respuesta: Escribir al mismo tiempo en el mismo socket

Hola:

El puerto tiene que estar abierto en los dos lados en caso de que haya firewall. El applet corre en el navegador, por lo que se ejecuta en el mismo ordenador donde esté el navegador (el pc del usuario).

Se bueno.
__________________
Apuntes Java
Wiki de Programación
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 18:01.