7

ただし、複数のランダム値を送信したいSocket。配列はそれらを送信するための最良の方法だと思います。しかし、配列を Socket に書き込む方法がわかりませんかOutputStream?

私のJavaクラス:

java.io.ByteArrayOutputStream をインポートします。import java.io.IOException; java.io.InputStream をインポートします。java.net.Socket をインポートします。java.io.* をインポートします。java.util.Random をインポートします。

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

}
4

7 に答える 7

8

java.io.DataOutputStream / DataInputStream ペアを使用します。これらは int の読み取り方法を知っています。長さ + 乱数のパケットとして情報を送信します。

差出人

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();
 ...
于 2012-12-21T05:19:27.070 に答える
4

Java配列は実際にはObjectであり、さらにインターフェースを実装してい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;
}

私は最初の答えも残しています(それも機能し、オブジェクトをUDPに書き込む場合やストリームがない場合に役立ちDatagramSocketsますDatagramPackets)。

于 2012-12-21T05:41:21.633 に答える
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);
   }
于 2012-12-21T04:24:47.883 に答える
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 ビットあたり 1 バイトのストップ ビット エンコード バイナリ。

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();
    }
}
于 2012-12-21T09:40:30.183 に答える
1

ストリームはバイトのストリームなので、データを一連のバイトにエンコードし、受信側でデコードする必要があります。データの書き込み方法は、エンコード方法によって異なります。

0 から 34 までの数字が 1 バイトに収まるので、これは次のように簡単に行うことができます。

outputStream.write(randomNumber); 

そして反対側:

int randomNumber = inputStream.read();

もちろん、バイトごとにストリームをフラッシュするのはあまり効率的ではありません (バイトごとにネットワーク パケットが生成され、各ネットワーク パケットには数十バイトのヘッダーとルーティング情報が含まれているため...)。パフォーマンスが重要な場合は、おそらく BufferedOutputStream も使用することをお勧めします。

于 2012-12-21T04:48:22.393 に答える
0

複数のランダムな値をソケットに送信する場合は、単純な形式を選択し、両方の当事者 (送信者と受信者) がそれに同意するよう;にします。そして送信

于 2012-12-21T04:27:56.917 に答える