2012-04-25 10 views
7

Come si progetta un ciclo di lettura e scrittura che funziona su un singolo socket (che supporta operazioni di lettura e scrittura parallele)? Devo usare più thread? La mia soluzione (java) va bene? Che mi dici di quel comando del sonno? Come lo usi all'interno di un tale ciclo?Best practice per la lettura/scrittura su una presa del server java

Sto cercando di utilizzare 2 Discussioni:

Leggi

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(); 
    } 
} 

Scrivi

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(); 
    } 
} 

Leggi non riesce a fornire un risultato corretto, dal momento che non v'è alcuna -1 inviato. Come posso risolvere questo problema?

Questo ciclo di sospensione/scrittura è una buona soluzione?

+1

È Java? Si prega di taggare la lingua –

+0

questa è java, ma questa è più una domanda di progettazione e non si riferisce a nessuna caratteristica java stessa – Schifty

+2

Vero, ma rende la domanda più specifica –

risposta

4

ci sono fondamentalmente tre modi per farlo rete I/O:

  1. Blocco. In questa modalità, le letture e le scritture verranno bloccate fino a quando non potranno essere soddisfatte, quindi se si desidera eseguire entrambe contemporaneamente, è necessario disporre di thread separati per ciascuno.

  2. Non bloccante. In questa modalità, letture e scritture restituiscono zero (Java) o in alcune lingue (C) un'indicazione di stato (return == -1, errno = EAGAIN/EWOULDBLOCK) quando non possono essere soddisfatte, quindi non è necessario utilizzare thread separati, ma hai bisogno di una terza API che ti dice quando le operazioni possono essere soddisfatte. Questo è lo scopo dell'API select().

  3. I/O asincrono, in cui si pianifica il trasferimento e viene restituito un tipo di handle tramite il quale è possibile interrogare lo stato del trasferimento o, in API più avanzate, un callback.

Si dovrebbe certamente mai usare lo stile while (in.available() > 0)/sleep() in uso qui. InputStream.available() ha pochi usi corretti e questo non è uno di questi, e il sonno è letteralmente una perdita di tempo. I dati possono arrivare entro il tempo di sospensione e un normale read() si dovrebbe riattivare immediatamente.

+0

Ti dispiacerebbe confrontare la tua prima e la seconda soluzione: come hai scelto il tuo approccio? il mio esempio sembra il tuo secondo approccio: come valuteresti la mia soluzione? – Schifty

+0

@Schifty Si tratta di quante connessioni è necessario gestire contemporaneamente.La funzione 'select()' è stata sviluppata prima dei thread, quando un'altra connessione significava invece un altro processo. I thread sono processi leggeri, quindi c'è un argomento che dice che non è mai necessario usare 'select()' in tutti questi giorni, e un altro argomento che dice che l'uso di 'select()' significa che stai trasformando la pianificazione dei thread del sistema operativo sovraccarico nei loop in-process. In questo momento della storia avrei usato thread fino ad almeno 10.000 connessioni, forse 100.000, a seconda della piattaforma. – EJP

0

È preferibile utilizzare una variabile booleana anziché (true) per chiudere correttamente il thread quando lo si desidera. Inoltre sì, dovresti creare thread multipli, uno per client connesso, poiché il thread si bloccherà fino a quando non verrà ricevuto un nuovo dato (con DataInputStream(). Read() per esempio). E no, questa non è davvero una domanda di design, ogni libreria/framework o linguaggi hanno il proprio modo di ascoltare da un socket, ad esempio per ascoltare da un socket in Qt si dovrebbe usare quello che viene chiamato "segnali e slot", non un ciclo infinito.

+0

DataInputStream(). Read() non blocca perché .available > 0 – Schifty

+0

@Schifty Ma non stai chiamando disponibile(), e non dovresti. – EJP