4

UDP以前はデータの送受信に使用していましTCPたが、パケット損失を避けるためにに切り替えたいと思います。

に関するいくつかのチュートリアルを読んだところ、のようなDatagramPacketを使用する代わりに、InputStream/OutputStreamを使用TCPしていることに気付きました。UDPTCP

DataInputStreamからbyte[]を取得するにはどうすればよいですか。これは次のようなものです。

byte[] receiveData = new byte[64000];
DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length); 
receiveData=receivePacket.getData();
4

2 に答える 2

13

ソケット (ストリーム) を介してメッセージ ベースのプロトコルを実装するには、基本的に何らかのメッセージ フォーマットを考え出し、それを接続の両端で読み書きする必要があります。非常に単純な形式は、メッセージの長さを 4 バイトの int として書き込み、メッセージのバイトを送信する (その後、ストリームをフラッシュする) ことです。受信側では、4 バイトの int を読み取り、次に続くバイト数を正確に読み取ります(読み取りメソッドの呼び出しを制限しないと、誤って次のメッセージの一部を読み取ってしまう可能性があることに注意してください)。

public void writeMessage(DataOutputStream dout, byte[] msg, int msgLen) {
  dout.writeInt(msgLen);
  dout.write(msg, 0, msgLen);
  dout.flush();
}

public byte[] readMessage(DataInputStream din) {
  int msgLen = din.readInt();
  byte[] msg = new byte[msgLen];
  din.readFully(msg);
  return msg;
}
于 2012-07-21T00:02:08.347 に答える
7

答えには 2 つの部分があります。あなたの質問が関連している 2 つの別々の問題に対処します。

1 . ネットワークの事実

TCP は本質的にストリーム ベースです。つまり、バイト [1000] を最初に送信してからバイト [1200] を送信することは、バイト [2200] を 1 回送信することと区別できません。ネットワークを介して実際に送信されるのは 2 つのパケットである可能性が非常に高く、最初は 1400 バイトのパケットで、2 つ目は 800 または 1401 と 799 のパケットであり、毎回異なる可能性があります。受信者は、送信者が実際に最初に 1000 バイトを送信し、次に 1200 バイトを送信したことを知る方法がありません。これは、ネットワークの設計によるものです。Java はこの事実とは何の関係もありません。そして、あなたはそれで何もできません。

2 . Java 実装

送信者側。まず、必要ですOutputStream os = tcpsocket.getOutputStream();。そして、毎回必要os.write(byteArray)です。受信側では、 が必要InputStream is = tcpsocket.getInputStream();です。そして、毎回必要is.read(byteArray)です。受信者側では、実際にどれだけbyteArray満たされたかが返されることに注意してください。1 から の容量までの任意の数値でありbyteArray、送信者が実際に送信した方法とは無関係です。

タスクを簡単にするためDataInputStream is = new DataInputStream(tcpsocket.getInputStream());に、最初に を使用し、is.readFully(byteArray)何かを読む必要があるたびに を使用できます。byteArrayこのようにして、常に満たされることが保証されます。

ただし、実際の長さが可変の場合、追加情報を追加しない限り、受け取るバイト数を知ることはできません。たとえば、4 バイトを使用して長さを最初に送信します。これを実際にどのように行うかは、通常、実際のユースケースと密接に関連しています。そしてそれはあなた次第です

于 2012-07-21T00:02:57.200 に答える