elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Curso de javascript por TickTack


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Java
| | | |-+  [RESUELTO]Crear una cola de conexiones de Socket en un ServerSocket.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [RESUELTO]Crear una cola de conexiones de Socket en un ServerSocket.  (Leído 5,059 veces)
NikNitro!


Desconectado Desconectado

Mensajes: 1.309


Galletaaa!!!


Ver Perfil WWW
[RESUELTO]Crear una cola de conexiones de Socket en un ServerSocket.
« en: 24 Mayo 2014, 15:25 pm »

Buenas, no estaba seguro de que preguntas de programación fueran en Redes, por lo que lo puse aquí.

Tengo un servidor que recibe conexiones de socket. Solo puede procesar una a la vez, pero quiero que si un segundo cliente intenta conectarse espere hasta que pueda. Había pensado hacerlo con una cola, pero no se "qué meter" dentro de la cola.

Aquí el code de mi Servidor:
Código
  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.PrintWriter;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7.  
  8.  
  9. public class Servidor extends Thread{
  10.  
  11. private int port;
  12. private ServerSocket server;
  13. private Socket sck;
  14.  
  15. public Servidor() {
  16. port = 5000;
  17.  
  18. }
  19. public Servidor(int i) {
  20. port = i;
  21.  
  22. }
  23.  
  24. public boolean Connect() {
  25. try {
  26.  
  27. server = new ServerSocket(port);
  28. System.out.println("Servidor esperando conexión.");
  29. sck = server.accept();
  30.  
  31. return true;
  32. } catch (IOException e) {
  33. // TODO Auto-generated catch block
  34. e.printStackTrace();
  35. System.out.println("Error con la conexión");
  36. return false;
  37. }
  38.  
  39. }
  40.  
  41. public boolean Disconnect() {
  42. try {
  43.  
  44. sck.close();
  45. server.close();
  46.  
  47. return true;
  48. } catch (IOException e) {
  49. // TODO Auto-generated catch block
  50. e.printStackTrace();
  51. System.out.println("Error al desconectar");
  52. return false;
  53. }
  54.  
  55. }
  56.  
  57. public boolean receiveMensaje() {
  58. try {
  59. PrintWriter printer = new PrintWriter(sck.getOutputStream(), true);
  60. BufferedReader reader = new BufferedReader(new InputStreamReader(sck.getInputStream()));
  61.  
  62. System.out.println("Esperando Mensaje...");
  63.  
  64. sck.setSoTimeout(40*1000);
  65. String mensaje = reader.readLine();
  66. while(sck.isConnected() && !mensaje.equals("FIN")) {
  67.  
  68. System.out.println("Recibido: "+mensaje);
  69. if(!mensaje.equals("FIN")) {
  70.  
  71. printer.println(mensaje.toUpperCase());
  72. mensaje = reader.readLine();
  73.  
  74. }
  75. }
  76.  
  77.  
  78. // System.out.println("Server apagandose");
  79. this.Disconnect();
  80.  
  81. return true;
  82. } catch (IOException e) {
  83. System.out.println("Error: Compruebe su conexion o que no ha estado más de 40 segundos inactivo.");
  84. Disconnect();
  85. return false;
  86. }
  87. }
  88.  
  89. public void run() {
  90. while(true) {
  91. Connect();
  92. receiveMensaje();
  93. }
  94. }
  95.  
  96.  
  97. public static void main(String[] args) {
  98. // TODO Auto-generated method stub
  99. Servidor sv = new Servidor();
  100. // Servidor sv = new Servidor(Integer.parseInt(args[0]));
  101. sv.run(); // Porque no necesita ser concurrente.
  102. }

Como veis, la conexion no es más que un 'Socket sck = ServerSocket.accept()"

Entonces cómo podría hacerlo?

Salud ;)


« Última modificación: 26 Mayo 2014, 21:44 pm por NikNitro! » En línea

Migugami

Desconectado Desconectado

Mensajes: 22


Systems Analyst


Ver Perfil
Re: Crear una cola de conexiones de socket.
« Respuesta #1 en: 24 Mayo 2014, 15:46 pm »

Se me ocurre que puedes hacer que cada conexión sea un thread y esperar por el término del thread actual. Creo que esto lo puedes hacer llamando al método join() en el thread que quieres se mantenga ejecutándose sin iniciar el otro thread que quiere ejecutarse, poniendo el thread B en cola de espera.

Código
  1. Conexion conexion = new Conexion().run();
  2. conexion.join();
  3. // aquí va el hilo que esperara que termine el hilo 'conexion'.


En línea

NikNitro!


Desconectado Desconectado

Mensajes: 1.309


Galletaaa!!!


Ver Perfil WWW
Re: Crear una cola de conexiones de socket.
« Respuesta #2 en: 26 Mayo 2014, 19:19 pm »

Mmm, perdón por la tardanza en la respuesta, pero quería responder con 'sustancia'.

Lo de los hilos no es lo que busco. Te explico:

El constructor de serverSocket que estoy usando es al que se le pasa un int que es el puerto, pero existe otro constructor tal que así:
Código:
new ServerSocket(int port, int backlog);

backlog indica el número de conexiones en espera que puede tener a la vez. Con el que yo estoy usando se usa como predeterminado el número 20 (o 50, ahora mismo no lo recuerdo bien).

Esto significa que la cola de conexiones está creada y, sin embargo, cuando cierro una conexion se me cierran todas las de la cola (todas van al mismo puerto y al cerrar el socket se cierran todas).

Total, si comento el close del serverSocket, cuando cierro la conexion desde el cliente me empiezan a dar una exageración de Throws en el receiveMessage().

Qué pensais que estoy haciendo mal? :s

Salud
En línea

Migugami

Desconectado Desconectado

Mensajes: 22


Systems Analyst


Ver Perfil
Re: Crear una cola de conexiones de socket.
« Respuesta #3 en: 26 Mayo 2014, 20:48 pm »

¿Cuando se cierran todas las conexiones, lanza alguna excepción (debería hacerlo) ? Si es así, coloca el StackTrace.

Te dejo un ejemplo extraído del libro Cómo programar en Java, que crea un servidor con una cola de conexiones:

Código
  1. // Configurar un servidor que reciba una conexión de un cliente, envíe
  2. // una cadena al cliente y cierre la conexión.
  3. import java.io.*;
  4. import java.net.*;
  5. import java.awt.*;
  6. import java.awt.event.*;
  7. import javax.swing.*;
  8.  
  9. public class Servidor extends JFrame {
  10.   private JTextField campoIntroducir;
  11.   private JTextArea areaPantalla;
  12.   private ObjectOutputStream salida;
  13.   private ObjectInputStream entrada;
  14.   private ServerSocket servidor;
  15.   private Socket conexion;
  16.   private int contador = 1;
  17.  
  18.   // configurar GUI
  19.   public Servidor()
  20.   {
  21.      super( "Servidor" );
  22.  
  23.      Container contenedor = getContentPane();
  24.  
  25.      // crear campoIntroducir y registrar componente de escucha
  26.      campoIntroducir = new JTextField();
  27.      campoIntroducir.setEditable( false );
  28.      campoIntroducir.addActionListener(
  29.         new ActionListener() {
  30.  
  31.            // enviar mensaje al cliente
  32.            public void actionPerformed( ActionEvent evento )
  33.            {
  34.               enviarDatos( evento.getActionCommand() );
  35.               campoIntroducir.setText( "" );
  36.            }
  37.         }  
  38.      );
  39.  
  40.      contenedor.add( campoIntroducir, BorderLayout.NORTH );
  41.  
  42.      // crear areaPantalla
  43.      areaPantalla = new JTextArea();
  44.      contenedor.add( new JScrollPane( areaPantalla ),
  45.         BorderLayout.CENTER );
  46.  
  47.      setSize( 300, 150 );
  48.      setVisible( true );
  49.  
  50.   } // fin del constructor de Servidor
  51.  
  52.   // configurar y ejecutar el servidor
  53.   public void ejecutarServidor()
  54.   {
  55.      // configurar servidor para que reciba conexiones; procesar las conexiones
  56.      try {
  57.  
  58.         // Paso 1: crear un objeto ServerSocket.
  59.         servidor = new ServerSocket( 12345, 100 );
  60.  
  61.         while ( true ) {
  62.  
  63.            try {
  64.               esperarConexion(); // Paso 2: esperar una conexión.
  65.               obtenerFlujos();        // Paso 3: obtener flujos de entrada y salida.
  66.               procesarConexion(); // Paso 4: procesar la conexión.
  67.            }
  68.  
  69.            // procesar excepción EOFException cuando el cliente cierre la conexión
  70.            catch ( EOFException excepcionEOF ) {
  71.               System.err.println( "El servidor terminó la conexión" );
  72.            }
  73.  
  74.            finally {
  75.               cerrarConexion();   // Paso 5: cerrar la conexión.
  76.               ++contador;
  77.            }
  78.  
  79.         } // fin de instrucción while
  80.  
  81.      } // fin del bloque try
  82.  
  83.      // procesar problemas con E/S
  84.      catch ( IOException excepcionES ) {
  85.         excepcionES.printStackTrace();
  86.      }
  87.  
  88.   } // fin del método ejecutarServidor
  89.  
  90.   // esperar que la conexión llegue, después mostrar información de la conexión
  91.   private void esperarConexion() throws IOException
  92.   {
  93.      mostrarMensaje( "Esperando una conexión\n" );
  94.      conexion = servidor.accept(); // permitir al servidor aceptar la conexión            
  95.      mostrarMensaje( "Conexión " + contador + " recibida de: " +
  96.         conexion.getInetAddress().getHostName() );
  97.   }
  98.  
  99.   // obtener flujos para enviar y recibir datos
  100.   private void obtenerFlujos() throws IOException
  101.   {
  102.      // establecer flujo de salida para los objetos
  103.      salida = new ObjectOutputStream( conexion.getOutputStream() );
  104.      salida.flush(); // vaciar búfer de salida para enviar información de encabezado
  105.  
  106.      // establecer flujo de entrada para los objetos
  107.      entrada = new ObjectInputStream( conexion.getInputStream() );
  108.  
  109.      mostrarMensaje( "\nSe recibieron los flujos de E/S\n" );
  110.   }
  111.  
  112.   // procesar la conexión con el cliente
  113.   private void procesarConexion() throws IOException
  114.   {
  115.      // enviar mensaje de conexión exitosa al cliente
  116.      String mensaje = "Conexión exitosa";
  117.      enviarDatos( mensaje );
  118.  
  119.      // habilitar campoIntroducir para que el usuario del servidor pueda enviar mensajes
  120.      establecerCampoTextoEditable( true );
  121.  
  122.      do { // procesar los mensajes enviados por el cliente
  123.  
  124.         // leer el mensaje y mostrarlo en pantalla
  125.         try {
  126.            mensaje = ( String ) entrada.readObject();
  127.            mostrarMensaje( "\n" + mensaje );
  128.         }
  129.  
  130.         // atrapar problemas que pueden ocurrir al tratar de leer del cliente
  131.         catch ( ClassNotFoundException excepcionClaseNoEncontrada ) {
  132.            mostrarMensaje( "\nSe recibió un tipo de objeto desconocido" );
  133.         }
  134.  
  135.      } while ( !mensaje.equals( "CLIENTE>>> TERMINAR" ) );
  136.  
  137.   } // fin del método procesarConexion
  138.  
  139.   // cerrar flujos y socket
  140.   private void cerrarConexion()
  141.   {
  142.      mostrarMensaje( "\nFinalizando la conexión\n" );
  143.      establecerCampoTextoEditable( false ); // deshabilitar campoIntroducir
  144.  
  145.      try {
  146.         salida.close();
  147.         entrada.close();
  148.         conexion.close();
  149.      }
  150.      catch( IOException excepcionES ) {
  151.         excepcionES.printStackTrace();
  152.      }
  153.   }
  154.  
  155.   // enviar mensaje al cliente
  156.   private void enviarDatos( String mensaje )
  157.   {
  158.      // enviar objeto al cliente
  159.      try {
  160.         salida.writeObject( "SERVIDOR>>> " + mensaje );
  161.         salida.flush();
  162.         mostrarMensaje( "\nSERVIDOR>>> " + mensaje );
  163.      }
  164.  
  165.      // procesar problemas que pueden ocurrir al enviar el objeto
  166.      catch ( IOException excepcionES ) {
  167.         areaPantalla.append( "\nError al escribir objeto" );
  168.      }
  169.   }
  170.  
  171.   // método utilitario que es llamado desde otros subprocesos para manipular a
  172.   // areaPantalla en el subproceso despachador de eventos
  173.   private void mostrarMensaje( final String mensajeAMostrar )
  174.   {
  175.      // mostrar mensaje del subproceso de ejecución despachador de eventos
  176.      SwingUtilities.invokeLater(
  177.         new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
  178.  
  179.            public void run() // actualiza areaPantalla
  180.            {
  181.               areaPantalla.append( mensajeAMostrar );
  182.               areaPantalla.setCaretPosition(
  183.                  areaPantalla.getText().length() );
  184.            }
  185.  
  186.         }  // fin de la clase interna
  187.  
  188.      ); // fin de la llamada a SwingUtilities.invokeLater
  189.   }
  190.  
  191.   // método utilitario que es llamado desde otros subprocesos para manipular a
  192.   // campoIntroducir en el subproceso despachador de eventos
  193.   private void establecerCampoTextoEditable( final boolean editable )
  194.   {
  195.      // mostrar mensaje del subproceso de ejecución despachador de eventos
  196.      SwingUtilities.invokeLater(
  197.         new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
  198.  
  199.            public void run()  // establece la capacidad de modificar a campoIntroducir
  200.            {
  201.               campoIntroducir.setEditable( editable );
  202.            }
  203.  
  204.         }  // fin de la clase interna
  205.  
  206.      ); // fin de la llamada a SwingUtilities.invokeLater
  207.   }
  208.  
  209.   public static void main( String args[] )
  210.   {
  211.      Servidor aplicacion = new Servidor();
  212.      aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
  213.      aplicacion.ejecutarServidor();
  214.   }
  215.  
  216. }  // fin de la clase Servidor

Código
  1. // Cliente que lee y muestra la información que le envía un Servidor.
  2. import java.io.*;
  3. import java.net.*;
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import javax.swing.*;
  7.  
  8. public class Cliente extends JFrame {
  9.   private JTextField campoIntroducir;
  10.   private JTextArea areaPantalla;
  11.   private ObjectOutputStream salida;
  12.   private ObjectInputStream entrada;
  13.   private String mensaje = "";
  14.   private String servidorChat;
  15.   private Socket cliente;
  16.  
  17.   // inicializar servidorChat y configurar GUI
  18.   public Cliente( String host )
  19.   {
  20.      super( "Cliente" );
  21.  
  22.      servidorChat = host; // establecer el servidor al que se va a conectar este cliente
  23.  
  24.      Container contenedor = getContentPane();
  25.  
  26.      // crear campoIntroducir y registrar componente de escucha
  27.      campoIntroducir = new JTextField();
  28.      campoIntroducir.setEditable( false );
  29.      campoIntroducir.addActionListener(
  30.         new ActionListener() {
  31.  
  32.            // enviar mensaje al servidor
  33.            public void actionPerformed( ActionEvent evento )
  34.            {
  35.               enviarDatos( evento.getActionCommand() );
  36.               campoIntroducir.setText( "" );
  37.            }
  38.         }  
  39.      );
  40.  
  41.      contenedor.add( campoIntroducir, BorderLayout.NORTH );
  42.  
  43.      // crear areaPantalla
  44.      areaPantalla = new JTextArea();
  45.      contenedor.add( new JScrollPane( areaPantalla ),
  46.         BorderLayout.CENTER );
  47.  
  48.      setSize( 300, 150 );
  49.      setVisible( true );
  50.  
  51.   } // fin del constructor de Cliente
  52.  
  53.   // conectarse al servidor y procesar mensajes del servidor
  54.   private void ejecutarCliente()
  55.   {
  56.      // conectarse al servidor, obtener flujos, procesar la conexión
  57.      try {
  58.         conectarAServidor(); // Paso 1: crear un socket para realizar la conexión
  59.         obtenerFlujos();      // Paso 2: obtener los flujos de entrada y salida
  60.         procesarConexion(); // Paso 3: procesar la conexión
  61.      }
  62.  
  63.      // el servidor cerró la conexión
  64.      catch ( EOFException excepcionEOF ) {
  65.         System.err.println( "El cliente termino la conexión" );
  66.      }
  67.  
  68.      // procesar los problemas que pueden ocurrir al comunicarse con el servidor
  69.      catch ( IOException excepcionES ) {
  70.         excepcionES.printStackTrace();
  71.      }
  72.  
  73.      finally {
  74.         cerrarConexion(); // Paso 4: cerrar la conexión
  75.      }
  76.  
  77.   } // fin del método ejecutarCliente
  78.  
  79.   // conectarse al servidor
  80.   private void conectarAServidor() throws IOException
  81.   {      
  82.      mostrarMensaje( "Intentando realizar conexión\n" );
  83.  
  84.      // crear Socket para realizar la conexión con el servidor
  85.      cliente = new Socket( InetAddress.getByName( servidorChat ), 12345 );
  86.  
  87.      // mostrar la información de la conexión
  88.      mostrarMensaje( "Conectado a: " +
  89.         cliente.getInetAddress().getHostName() );
  90.   }
  91.  
  92.   // obtener flujos para enviar y recibir datos
  93.   private void obtenerFlujos() throws IOException
  94.   {
  95.      // establecer flujo de salida para los objetos
  96.      salida = new ObjectOutputStream( cliente.getOutputStream() );      
  97.      salida.flush(); // vacíar búfer de salida para enviar información de encabezado
  98.  
  99.      // establecer flujo de entrada para los objetos
  100.      entrada = new ObjectInputStream( cliente.getInputStream() );
  101.  
  102.      mostrarMensaje( "\nSe recibieron los flujos de E/S\n" );
  103.   }
  104.  
  105.   // procesar la conexión con el servidor
  106.   private void procesarConexion() throws IOException
  107.   {
  108.      // habilitar campoIntroducir para que el usuario del cliente pueda enviar mensajes
  109.      establecerCampoTextoEditable( true );
  110.  
  111.      do { // procesar mensajes enviados del servidor
  112.  
  113.         // leer mensaje y mostrarlo en pantalla
  114.         try {
  115.            mensaje = ( String ) entrada.readObject();
  116.            mostrarMensaje( "\n" + mensaje );
  117.         }
  118.  
  119.         // atrapar los problemas que pueden ocurrir al leer del servidor
  120.         catch ( ClassNotFoundException excepcionClaseNoEncontrada ) {
  121.            mostrarMensaje( "\nSe recibió un objeto de tipo desconocido" );
  122.         }
  123.  
  124.      } while ( !mensaje.equals( "SERVIDOR>>> TERMINAR" ) );
  125.  
  126.   } // fin del método procesarConexion
  127.  
  128.   // cerrar flujos y socket
  129.   private void cerrarConexion()
  130.   {
  131.      mostrarMensaje( "\nCerrando conexión" );
  132.      establecerCampoTextoEditable( false ); // deshabilitar campoIntroducir
  133.  
  134.      try {
  135.         salida.close();
  136.         entrada.close();
  137.         cliente.close();
  138.      }
  139.      catch( IOException excepcionES ) {
  140.         excepcionES.printStackTrace();
  141.      }
  142.   }
  143.  
  144.   // enviar mensaje al servidor
  145.   private void enviarDatos( String mensaje )
  146.   {
  147.      // enviar objeto al servidor
  148.      try {
  149.         salida.writeObject( "CLIENTE>>> " + mensaje );
  150.         salida.flush();
  151.         mostrarMensaje( "\nCLIENTE>>> " + mensaje );
  152.      }
  153.  
  154.      // procesar los problemas que pueden ocurrir al enviar el objeto
  155.      catch ( IOException excepcionES ) {
  156.         areaPantalla.append( "\nError al escribir el objeto" );
  157.      }
  158.   }
  159.  
  160.   // método utilitario que es llamado desde otros subprocesos para manipular a
  161.   // areaPantalla en el subproceso despachador de eventos
  162.   private void mostrarMensaje( final String mensajeAMostrar )
  163.   {
  164.      // mostrar mensaje del subproceso de ejecución de la GUI
  165.      SwingUtilities.invokeLater(
  166.         new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
  167.  
  168.            public void run() // actualiza areaPantalla
  169.            {
  170.               areaPantalla.append( mensajeAMostrar );
  171.               areaPantalla.setCaretPosition(
  172.                  areaPantalla.getText().length() );
  173.            }
  174.  
  175.         }  // fin de la clase interna
  176.  
  177.      ); // fin de la llamada a SwingUtilities.invokeLater
  178.   }
  179.  
  180.   // método utilitario que es llamado desde otros subprocesos para manipular a
  181.   // campoIntroducir en el subproceso despachador de eventos
  182.   private void establecerCampoTextoEditable( final boolean editable )
  183.   {
  184.      // mostrar mensaje del subproceso de ejecución de la GUI
  185.      SwingUtilities.invokeLater(
  186.         new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
  187.  
  188.            public void run()  // establece la capacidad de modificar campoIntroducir
  189.            {
  190.               campoIntroducir.setEditable( editable );
  191.            }
  192.  
  193.         }  // fin de la clase interna
  194.  
  195.      ); // fin de la llamada a SwingUtilities.invokeLater
  196.   }
  197.  
  198.   public static void main( String args[] )
  199.   {
  200.      Cliente aplicacion;
  201.  
  202.      if ( args.length == 0 )
  203.         aplicacion = new Cliente( "127.0.0.1" );
  204.      else
  205.         aplicacion = new Cliente( args[ 0 ] );
  206.  
  207.      aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
  208.      aplicacion.ejecutarCliente();
  209.   }
  210.  
  211. } // fin de la clase Cliente
En línea

NikNitro!


Desconectado Desconectado

Mensajes: 1.309


Galletaaa!!!


Ver Perfil WWW
Re: Crear una cola de conexiones de socket.
« Respuesta #4 en: 26 Mayo 2014, 21:41 pm »

Ok. El fallo estaba únicamente en que cuando acababa una conexion cerraba el serverSocket y luego creaba uno nuevo. He puesto el constructor del serverSocket en el constructor de Servidor y le he quitado el .close().

Si alguien necesita el código completo que me lo pida. De todos modos a partir del día 8 (que es cuando entrego la práctica) lo subiré a mi blog ;)
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Ayuda para crear un socket en C
Programación C/C++
Norochii 3 3,440 Último mensaje 5 Noviembre 2011, 12:25 pm
por Queta
pasar datos de una cola dinámica a otra cola...
Programación C/C++
include (); 4 9,543 Último mensaje 10 Agosto 2012, 10:01 am
por BlackZeroX
Problemita con serversocket
Java
chrs1214 0 1,594 Último mensaje 19 Septiembre 2013, 14:08 pm
por chrs1214
¿Qué ocurre al crear un socket?
Programación C/C++
mester 3 1,870 Último mensaje 23 Noviembre 2015, 22:19 pm
por ivancea96
socket, serversocket, interoperacion con otros lenguaje.
Java
bash 0 1,483 Último mensaje 1 Enero 2017, 21:47 pm
por bash
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines