2012-12-21 29 views
6

我想通過Socket發送多個隨機值。我認爲數組是發送它們的最佳方式。但是我不知道如何向Socket outputStream寫入數組?如何在Java中將數組寫入outputStream

我的Java類

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

什麼是錯的代碼?什麼和如何不起作用? –

+0

你得到的錯誤是什麼 – Shurmajee

+0

從他的解釋看來,他希望在一次調用write()時發送一組消息,而不是迭代數組並通過字符串 –

回答

7

使用java.io.DataOutputStream/DataInputStream對,他們知道如何讀取整數。以長度+隨機數字的包發送信息。

發件人

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)) 
... 

接收機

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

+1發送者和接收者的寫邏輯 –

2

我會建議簡單地使用一些分隔符例如串聯在字符串中int@@,然後一次發送最終的連接字符串。在接收端,只需使用相同的分隔符來獲得int[]回例如分割字符串:

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

在接收端,讓您的字符串分割爲:

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使用@@對數字來說可能是過量的。一個簡單的空間會做。 –

+0

@PeterLawrey同意。我已經提到要使用任何分隔符。 –

0

,如果你想送給套接字選擇一個以上的隨機值,選擇一個簡單的格式並讓雙方同意(發送方和接收方),例如,您可以簡單地選擇一個分隔符,如;,然後創建一個帶有該分隔符的所有值的字符串,然後發送

1

嗯,流是字節流,所以您必須將數據編碼爲字節序列,並在接收端對其進行解碼。如何編寫數據取決於您想如何編碼數據。

如從0到34配合在一個單一的字節數,這可以是那麼容易,因爲:

outputStream.write(randomNumber); 

和在另一側上:

int randomNumber = inputStream.read(); 

當然,沖洗後的流每個字節的效率都不高(因爲它會爲每個字節生成一個網絡數據包,而每個網絡數據包包含數十個字節的標頭和路由信息......)。如果性能很重要,您可能也想使用BufferedOutputStream。

3

Java數組實際上是Object S和此外,他們實現Serializable接口。因此,您可以序列化您的數組,獲取字節並通過套接字發送這些字節。這應做到:

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

什麼是真正整潔的這個是,它不僅爲int[]但對於任何Serializable對象。

編輯: 它又在想,這是更簡單:

發件人

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

接收機

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

我要離開我第一個答案也是(它也是o工作,並且)將對象寫入UDP DatagramSocketsDatagramPackets(其中沒有流)是很有用的。

+0

你需要先發送長度,否則你將無法閱讀任何事情後。 –

+0

@PeterLawrey解釋? 'write(byte [] b)'將'b.length'字節寫入流中。 – AFS

+0

假設你調用了兩次,你會如何知道第一個數組何時完成並且下一個數組開始了?即嘗試閱讀這種格式,你會發現它非常困難。 btw +1 –

1

所以你可以比較我已經寫了一個模板的替代格式,它允許你使用任何格式你的願望,或比較替代品。

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

二進制格式,4個字節的整數

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

停止位編碼二進制每7個比特的一個字節。

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

在最後用新行編碼的文本。

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修改接收整數,而不是字符串數組:

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