2012-12-21 1 views
6

Desidero inviare più di un valore casuale tramite Socket. Penso che array sia il modo migliore per inviarli ... Ma non so come scrivere un array su Socket outputStream?come scrivere array su outputStream in Java

mio java Classe

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.Socket; 
import java.io.*; 
import java.util.Random; 

class NodeCommunicator { 

public static void main(String[] args) { 
try { 
    Socket nodejs = new Socket("localhost", 8181); 

     Random randomGenerator = new Random(); 
     for (int idx = 1; idx <= 1000; ++idx){ 
      Thread.sleep(500); 
      int randomInt = randomGenerator.nextInt(35); 
      sendMessage(nodejs, randomInt + " "); 
      System.out.println(randomInt); 
     } 

     while(true){ 
      Thread.sleep(1000); 
     } 

} catch (Exception e) { 
    System.out.println("Connection terminated..Closing Java Client"); 
    System.out.println("Error :- "+e); 
    } 

} 
     public static void sendMessage(Socket s, String message) throws IOException { 
      s.getOutputStream().write(message.getBytes("UTF-8")); 
      s.getOutputStream().flush(); 
     } 




} 
+3

cosa c'è di sbagliato con questo codice? cosa e come non funziona? –

+0

Qual è l'errore che stai ricevendo – Shurmajee

+0

Dalla sua spiegazione, sembra che voglia inviare una serie di messaggi in una chiamata a write(), invece di scorrere sull'array e inviare ogni stringa per stringa –

risposta

7

Utilizza la coppia java.io.DataOutputStream/DataInputStream, sanno come leggere i messaggi. Invia informazioni come pacchetto di lunghezza + numeri casuali.

mittente

Socket sock = new Socket("localhost", 8181); 
DataOutputStream out = new DataOutputStream(sock.getOutputStream()); 
out.writeInt(len); 
for(int i = 0; i < len; i++) { 
     out.writeInt(randomGenerator.nextInt(35)) 
... 

ricevitore

DataInputStream in = new DataInputStream(sock.getInputStream()); 
int len = in.readInt(); 
for(int i = 0; i < len; i++) { 
     int next = in.readInt(); 
... 
+0

+1 per scrivere la logica per il mittente e il destinatario –

2

Vorrei consigli per concatenare semplicemente i valori int in una stringa utilizzando alcuni delimitatore per esempio @@, quindi trasmettere la stringa concatenata finale in una sola volta. Sul lato ricevente, basta dividere la stringa utilizzando lo stesso delimitatore per ottenere l'esempio int[] posteriore:

Random randomGenerator = new Random(); 
    StringBuilder numToSend = new StringBuilder(""); 
    numToSend.append(randomGenerator.nextInt(35)); 

    for (int idx = 2; idx <= 1000; ++idx){ 
     Thread.sleep(500); 
     numToSend.append("@@").append(randomGenerator.nextInt(35)); 
    } 
    String numsString = numToSend.toString(); 
    System.out.println(numsString); 
    sendMessage(nodejs, numsString); 

sul lato ricevente, ottenere la stringa e diviso come:

Socket remotejs = new Socket("remotehost", 8181); 
    BufferedReader in = new BufferedReader(
           new InputStreamReader(remotejs.getInputStream())); 
    String receivedNumString = in.readLine(); 
    String[] numstrings = receivedNumString.split("@@"); 
    int[] nums = new int[numstrings.length]; 
    int indx = 0; 
    for(String numStr: numstrings){ 
    nums[indx++] = Integer.parseInt(numStr); 
    } 
+0

+1 L'uso di @@ è forse eccessivo per i numeri. Uno spazio semplice farebbe. –

+0

@PeterLawrey Accetto. Ho già detto di usare qualsiasi delimitatore. –

0

se si desidera inviare più di un valore casuale per il socket, scegliere un formato semplice e rendere entrambe le parti d'accordo (mittente e ricevitore), ad esempio si può semplicemente scegliere un separatore come ; e creare una stringa con tutti i valori con quel separatore e quindi inviare

1

Bene, uno stream è un flusso di byte, quindi è necessario codificare i dati in una sequenza di byte e decodificarli sul lato ricevente. Come scrivere i dati dipende da come lo vuoi codificare.

Come numeri da 0 a 34 in forma in un singolo byte, questo può essere semplice come:

outputStream.write(randomNumber); 

e dall'altro lato:

int randomNumber = inputStream.read(); 

Naturalmente, il lavaggio del flusso dopo ogni byte non è molto efficiente (poiché genererà un pacchetto di rete per ogni byte e ogni pacchetto di rete contiene dozzine di byte di intestazione e informazioni di routing ...). Se le prestazioni sono importanti, probabilmente vorrai utilizzare anche BufferedOutputStream.

3

array Java sono effettivamente Object s ed inoltre implementano l'interfaccia Serializable. Quindi, è possibile serializzare la matrice, ottenere i byte e inviarli tramite il socket. Questo dovrebbe farlo:

public static void sendMessage(Socket s, int[] myMessageArray) 
    throws IOException { 
    ByteArrayOutputStream bs = new ByteArrayOutputStream(); 
    ObjectOutputStream os = new ObjectOutputStream(bs); 
    os.writeObject(myMessageArray); 
    byte[] messageArrayBytes = bs.toByteArray(); 
    s.getOutputStream().write(messageArrayBytes); 
    s.getOutputStream().flush(); 
} 

Che cosa è veramente pulito su questo è che funziona non solo per int[] ma per qualsiasi Serializable oggetto.

Edit: Pensando di nuovo, questo è ancora più semplice:

mittente:

public static void sendMessage(Socket s, int[] myMessageArray) 
    throws IOException { 
    OutputStream os = s.getOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(os); 
    oos.writeObject(myMessageArray); 
} 

ricevitore:

public static int[] getMessage(Socket s) 
    throws IOException { 
    InputStream is = s.getInputStream(); 
    ObjectInputStream ois = new ObjectInputStream(is); 
    int[] myMessageArray = (int[])ois.readObject(); 
    return myMessageArray; 
} 

Sto lasciando la mia prima risposta anche come (als o funziona e) è utile per scrivere oggetti su UDP DatagramSockets e DatagramPackets dove non ci sono stream.

+0

è necessario inviare prima la lunghezza altrimenti non sarà più possibile leggere nulla dopo questo. –

+0

@PeterLawrey spiega? 'write (byte [] b)' scrive byte 'b.length' sullo stream. – AFS

+0

Supponiamo che tu lo chiami due volte, come faresti a sapere quando il primo array è finito e viene avviato il prossimo array? provate a leggere questo formato e lo troverete molto difficile. btw +1 –

1

Quindi è possibile confrontare i formati alternativi che ho scritto un modello che consente di utilizzare qualsiasi formato desiderato o confrontare le alternative.

abstract class DataSocket implements Closeable { 
    private final Socket socket; 
    protected final DataOutputStream out; 
    protected final DataInputStream in; 

    DataSocket(Socket socket) throws IOException { 
     this.socket = socket; 
     out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); 
     in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); 
    } 

    public void writeInts(int[] ints) throws IOException { 
     writeInt(ints.length); 
     for (int i : ints) 
      writeInt(i); 
     endOfBlock(); 
    } 

    protected abstract void writeInt(int i) throws IOException; 

    protected abstract void endOfBlock() throws IOException; 

    public int[] readInts() throws IOException { 
     nextBlock(); 
     int len = readInt(); 
     int[] ret = new int[len]; 
     for (int i = 0; i < len; i++) 
      ret[i] = readInt(); 
     return ret; 
    } 

    protected abstract void nextBlock() throws IOException; 

    protected abstract int readInt() throws IOException; 

    public void close() throws IOException { 
     out.close(); 
     in.close(); 
     socket.close(); 
    } 
} 

formato binario, int 4 byte

binario codificato
class BinaryDataSocket extends DataSocket { 
    BinaryDataSocket(Socket socket) throws IOException { 
     super(socket); 
    } 

    @Override 
    protected void writeInt(int i) throws IOException { 
     out.writeInt(i); 
    } 

    @Override 
    protected void endOfBlock() throws IOException { 
     out.flush(); 
    } 

    @Override 
    protected void nextBlock() { 
     // nothing 
    } 

    @Override 
    protected int readInt() throws IOException { 
     return in.readInt(); 
    } 
} 

bit di stop con un byte per 7 bit.

class CompactBinaryDataSocket extends DataSocket { 
    CompactBinaryDataSocket(Socket socket) throws IOException { 
     super(socket); 
    } 

    @Override 
    protected void writeInt(int i) throws IOException { 
     // uses one byte per 7 bit set. 
     long l = i & 0xFFFFFFFFL; 
     while (l >= 0x80) { 
      out.write((int) (l | 0x80)); 
      l >>>= 7; 
     } 
     out.write((int) l); 
    } 

    @Override 
    protected void endOfBlock() throws IOException { 
     out.flush(); 
    } 

    @Override 
    protected void nextBlock() { 
     // nothing 
    } 

    @Override 
    protected int readInt() throws IOException { 
     long l = 0; 
     int b, count = 0; 
     while ((b = in.read()) >= 0x80) { 
      l |= (b & 0x7f) << 7 * count++; 
     } 
     if (b < 0) throw new EOFException(); 
     l |= b << 7 * count; 
     return (int) l; 
    } 
} 

testo codificato con una nuova riga alla fine.

class TextDataSocket extends DataSocket { 
    TextDataSocket(Socket socket) throws IOException { 
     super(socket); 
    } 

    private boolean outBlock = false; 

    @Override 
    protected void writeInt(int i) throws IOException { 
     if (outBlock) out.write(' '); 
     out.write(Integer.toString(i).getBytes()); 
     outBlock = true; 
    } 

    @Override 
    protected void endOfBlock() throws IOException { 
     out.write('\n'); 
     out.flush(); 
     outBlock = false; 
    } 

    private Scanner inLine = null; 

    @Override 
    protected void nextBlock() throws IOException { 
     inLine = new Scanner(in.readLine()); 
    } 

    @Override 
    protected int readInt() throws IOException { 
     return inLine.nextInt(); 
    } 
} 
0

Android Socket SERVER Example modificati per ricevere array di interi, invece di stringhe:

... 
class CommunicationThread implements Runnable { 

    private ObjectInputStream input; 

    public CommunicationThread(Socket clientSocket) { 

     try { 

      this.input = new ObjectInputStream(clientSocket.getInputStream()); 

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

    public void run() { 

     while (!Thread.currentThread().isInterrupted()) { 

      try { 

       int[] myMessageArray = (int[]) input.readObject(); 

       String read = null; 
       read = String.format("%05X", myMessageArray[0] & 0x0FFFFF); 
       int i = 1; 
       do { 
        read = read + ", " + String.format("%05X", myMessageArray[i] & 0x0FFFFF); 
        i++; 
       } while (i < myMessageArray.length); 
       read = read + " (" + myMessageArray.length + " bytes)"; 

       updateConversationHandler.post(new updateUIThread(read)); 

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