Problema a la hora de invocar otras clases desde la clase principal

Iniciado por Silver1101, 15 Septiembre 2017, 20:28 PM

0 Miembros y 1 Visitante están viendo este tema.

Silver1101

PROBLEMA A LA HORA DE INVOCAR OTRAS CLASES DESDE LA CLASE PRINCIPAL.

Pues estoy programando un chat a través de Sockets usando Netbeans, en el que tengo por un lado en un paquete, la clase Servidor, y en otro paquete la clase Cliente. En principio el programa funciona bien, cada paquete tiene sus respectivas clases con sus métodos de envío y recepción de mensaje, cada uno con su clase principal en el que tienen bien definida la IP y los puertos para conectarse.



Si ejecuto el servidor, y luego el cliente por separado, todo funciona perfecto (tal y como se ve en la imagen). El problema surge cuando quiero crear un panel principal con dos botones, (Servidor y Cliente), de modo que cuando pulso el botón servidor, que se me abra la ventana del servidor, y después si pulso el botón cliente, que me aparezca la ventana del cliente. Para eso utilizo el código de siempre para invocar otras clases:

private void btnServidorActionPerformed(java.awt.event.ActionEvent evt) {  

       PrincipalChatS verS=new PrincipalChatS();

//La primera línea es para asignarle la acción al botón del Servidor (llamado btnServidor). La segunda línea sirve para invocar la clase.

Con este código consigo (aunque parcialmente) mi objetivo, y cuando pulso el botón servidor me aparece la ventana del servidor, y lo mismo me pasa con el cliente, el problema es que no funcionan. Como se ve en la siguiente imagen:



Aquí dejo el código de la interfaz del Servidor (con el nombre de clase "PrincipalChatS"). He marcado en rojo la parte donde hago el Listen




Y para el cliente el código donde pongo el listen es este:



Al lado del código pongo para que pongo cada cosa, para que se vea más o menos para que es cada parte del código.

Pero el problema es ese. Al invocarlos desde otra clase, no funcionan.

¿por qué no funcionan cuando los invoco, y en cambio sí me funcionan si los ejecuto directamente, si el código es el mismo?

AlbertoBSD

Sin ver el codigo, poco te podriamos ayudar, en teoria deberia de funcionar, pero hay que ver en que interfaz de red, esta haciendo el Listen y en cual esta buscando al cliente.

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

Serapis

#2
Efectivamente, como te dice AlbertoBSD, sin código, no se puede decir mucho, es jugar a adivinar...

Sin embargo normalmente cuando todo funciona y esto falla, lo que suele suceder (con bastante frecuencia), es que el servidor crea una instancia y el cliente llama a otra instancia de la clase servidor...

La solución es que exista una y solo una clase servidor...

Un poco de pseudocódigo te ayudará a entender el problema y facilitar la solución (dado el caso que éste sea el problema).

Clase Cliente
  Server Servidor

  Buleano = Funcion Conectar(x,y,z)  //x,y,z son posibles parámetros necesarios para la conexión, aquí se omite por claridad...
      Servidor = nueve Server //x,y,z
  Fin Funcion

  // Otros métodos de la clase...
Fin Clase

Como se ve, aquí se crea una instancia dle servidor... una instancia nueva, a la que se le asigna un espacio de memoria... y cada cliente... creará una instancia distinta, habrá tantas instancias distintas del servidor como clientes lo llamen.


Solución: Crear una clase y método estático... que contenga el servidor.
Así se crea una única instancia para todos los que llamen. La clase servidor, no puede ser creada desde fuera, pero puede ser instanciada, y exclusivamente invocando este método... La clase 'server' es pública pero 'no creatable', así esta clase crea una única instancia del servidor y sirve por tanto siempre la misma instancia a todos los clientes...

Clase estatica ProveedorServer
   Server p_Servidor  privado

   Server = Funcion IniciarServidor
       Si (p_Servidor no existe) luego    
           p_Servidor = Nuevo Server
       Fin si

       Devolver p_Servidor
   Fin funcion
   
   // Otros métodos que fueren necesarios para la clase...
Fin clase


que sería llamado así:
Clase Cliente
  Server Servidor
  ProveedorServer Proveedor

  Funcion Nueva //instancia
      Proveedor = Nuevo ProveedorServer
  Fin funcino

  Buleano = Funcion Conectar(x,y,z)  //x,y,z son posibles parámetros necesarios para la conexión, aquí se omite por claridad...
      Servidor = Proveedor.IniciarServidor //x,y,z
      Devolver Existe(Servidor)  //Existe: Comprueba que es una instancia válida de objeto.
  Fin Funcion

  // Otros métodos de la clase...
Fin Clase


Un modo de probar que es correcto, es hacer lo siguiente.

Crear un método de prueba en el servidor:

Clase Server
   Entero p_Numero

   Funcion Nueva // Instancia
       p_Numero = NumeroAlAzar(entre 1millon y 10millones)     //crea un número al azar
   Fin funcion

   Entero = Funcion Probar
       Devolver p_Numero
   Fin funcion
Fin clase


Ahora para probar si son la misma instancia cuando se crea un cliente y se comunica con el servidor, luego invoca su método Probar:
Clase Cliente  
   // .... ya tiene sus métodos, esto es un añadido al método conectar...
   
   Buleano = Funcion Conectar(x,y,z)
      Servidor = Proveedor.IniciarServidor
      Mensaje Servidor.Probar  // <------------------------ Aquí probando el servidor...
      Devolver Existe(Servidor)
  Fin Funcion
 
Fin clase

Si existe una única instancia dle servidor, el número de la prueba debe ser siempre el mismo hasta que se destruya el servidor.
Si el servidor fue creado y luego cada cliente ofrece distintos números de prueba, es que se están creando instancias exclusivas para cada cliente...

Silver1101

Muchas gracias AlbertoBSD y NEBIRE, pues he modificado el post, y he añadido el código del Servidor y el código del Cliente en el que hago el listen, para poder dar mas información.

Lo que no entiendo del todo es esto que me explicas NEBIRE. Entiendo que solo tiene que haber una única clase Servidor (pero ya lo hago ¿no?) solo tengo una clase servidor y solo le hago una sola instancia en la misma clase. ¿no seria correcto?. De todos modos estoy repasando mejor los ejemplo de código que me has puesto, porque estoy seguro de que has dado en el clavo.

Gracias!!!


Serapis

Sí, has creado una clase servidor, y una sola instancia, pero... ...esa y solo esa instancia es la que debe ser visible a todos. Ninguna otra instancia de esa clase.
Para que eso sea posible, debe crearse una única instancia, no importa cuantas veces se pretenda crear instancias de clase.

Y el modo de lograr esto, es crearla ya tu y guardarla... y quien solicite una instancia (no debe poder crearse desde fuera delservidor), tu le entregas una referencia.

Así todos tienen exactamente la misma instancia, porque siempre entregas la referencia a la única clase creada...


Para asegurarte que lo haces bien, debes hacer alguna prueba, como la que te sugerí aquí:
Cita de: NEBIRE en 15 Septiembre 2017, 21:28 PM
Un modo de probar que es correcto, es hacer lo siguiente.

Crear un método de prueba en el servidor:

Clase Server
   Entero p_Numero

   Funcion Nueva // Instancia
       p_Numero = NumeroAlAzar(entre 1millon y 10millones)     //crea un número al azar
   Fin funcion

   Entero = Funcion Probar
       Devolver p_Numero
   Fin funcion
Fin clase


Ahora para probar si son la misma instancia cuando se crea un cliente y se comunica con el servidor, luego invoca su método Probar:
Clase Cliente  
   // .... ya tiene sus métodos, esto es un añadido al método conectar...
   
   Buleano = Funcion Conectar(x,y,z)
      Servidor = Proveedor.IniciarServidor
      Mensaje Servidor.Probar  // <------------------------ Aquí probando el servidor...
      Devolver Existe(Servidor)
  Fin Funcion
 
Fin clase

Si existe una única instancia dle servidor, el número de la prueba debe ser siempre el mismo hasta que se destruya el servidor.
Si el servidor fue creado y luego cada cliente ofrece distintos números de prueba, es que se están creando instancias exclusivas para cada cliente...

Silver1101

Pues si, ahí estaba el fallo, ahora ya me funciona de forma correcta, y los he estado probando.
¡¡¡Muchísimas gracias por tu ayuda NEBIRE !!!  no me habría dado cuenta de los errores si no llega a ser por la explicación.