2012-04-25 15 views
7

¿Cómo se diseña un bucle de lectura y escritura que funciona en un solo zócalo (que admite operaciones paralelas de lectura y escritura)? ¿Tengo que usar múltiples hilos? ¿Mi solución (java) es buena? ¿Qué hay de ese comando de dormir? ¿Cómo se usa eso dentro de ese circuito?Práctica recomendada para leer/escribir en un socket de servidor Java

Estoy tratando de utilizar 2 Temas:

Leer

public void run() { 
    InputStream   clientInput; 
    ByteArrayOutputStream byteBuffer; 
    BufferedInputStream bufferedInputStream; 
    byte[]    data; 
    String    dataString; 
    int     lastByte; 

    try { 
     clientInput   = clientSocket.getInputStream(); 
     byteBuffer   = new ByteArrayOutputStream(); 
     bufferedInputStream = new BufferedInputStream(clientInput); 

     while(isRunning) { 

      while ((lastByte = bufferedInputStream.read()) > 0) { 
       byteBuffer.write(lastByte); 
      } 
       data  = byteBuffer.toByteArray(); 
       dataString = new String(data); 
       byteBuffer.reset();  
     } 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Escribir

public void run() { 
    OutputStream clientOutput; 
    byte[]  data; 
    String  dataString; 

    try { 
     clientOutput = clientSocket.getOutputStream(); 

     while(isOpen) { 

      if(!commandQueue.isEmpty()) { 
       dataString = commandQueue.poll(); 
       data  = dataString.getBytes(); 
       clientOutput.write(data); 
      }     
      Thread.sleep(1000); 
     }  
     clientOutput.close();   
    } 
    catch (IOException e) { 
     e.printStackTrace(); 
    } 
    catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

Lee no puede entregar un resultado adecuado, ya que no hay -1 envió. ¿Cómo resuelvo este problema?

¿Es este bucle de suspensión/escritura una buena solución?

+1

¿Es esto Java? Por favor marque el idioma –

+0

esto es java, pero esto es más una cuestión de diseño y no se relaciona con ninguna característica java en sí – Schifty

+2

Es cierto, pero hace que la pregunta sea más específica –

Respuesta

4

Básicamente, hay tres maneras de hacer la red de E/S:

  1. bloqueo. En este modo, las lecturas y escrituras se bloquearán hasta que puedan cumplirse, por lo que si quiere hacer ambas cosas simultáneamente, necesita hilos separados para cada una.

  2. Sin bloqueo. En este modo, las lecturas y escrituras devolverán cero (Java) o en algunos idiomas (C) una indicación de estado (return == -1, errno = EAGAIN/EWOULDBLOCK) cuando no puedan cumplirse, por lo que no necesita hilos separados, pero necesita una tercera API que le indique cuándo se pueden cumplir las operaciones . Este es el propósito de la API select().

  3. E/S asincrónica, en la que programa la transferencia y se le devuelve un tipo de identificador a través del cual puede consultar el estado de la transferencia o, en las API más avanzadas, una devolución de llamada.

Debe ciertamente nunca utilice el estilo while (in.available() > 0)/sleep() está utilizando aquí. InputStream.available() tiene pocos usos correctos y este no es uno de ellos, y el sueño es literalmente una pérdida de tiempo. Los datos pueden llegar dentro del tiempo de inactividad, y un read() normal se activaría inmediatamente.

+0

¿Te importaría comparar tu primera y segunda solución? ¿Cómo eliges tu enfoque? mi ejemplo se parece a su segundo enfoque: ¿cómo calificaría mi solución? – Schifty

+0

@Schifty Se reduce a la cantidad de conexiones que necesita manejar a la vez.La función 'select()' se desarrolló antes de los hilos, cuando otra conexión significaba otro proceso. Los subprocesos son procesos ligeros, por lo que hay un argumento que dice que nunca necesitará usar 'select()' en todos estos días, y otro argumento que dice que usar 'select()' significa que está transformando la programación de hilos del sistema operativo sobrecarga en bucles en proceso. En este momento de la historia, utilizaría subprocesos hasta por lo menos 10.000 conexiones, tal vez 100.000, dependiendo de la plataforma. – EJP

0

Debería utilizar una variable booleana en lugar de while (verdadero) para cerrar correctamente el hilo cuando lo desee. También sí, debes crear múltiples hilos, uno por cliente conectado, ya que el hilo se bloqueará hasta que se reciban nuevos datos (con DataInputStream(). Read() por ejemplo). Y no, esto no es realmente una cuestión de diseño, cada biblioteca/Framework o idiomas tienen su propia forma de escuchar desde un socket, por ejemplo, para escuchar desde un socket en Qt debes usar lo que se llama "señales y ranuras", no un Bucle infinito.

+0

DataInputStream(). Read() no se bloquea porque .disponible > 0 – Schifty

+0

@Schifty Pero no está llamando disponible(), y no debería. – EJP

Cuestiones relacionadas