0

UTF-8 文字列を C# TCP サーバーに送信する Java クライアントがあります。DataOutputStream を使用して文字列を送信しています。コードは次のようになります。

public void sendUTF8String(String ar) {
    if (socket.isConnected()) {
        try {
            dataOutputStream.write(ar.getBytes(Charset.forName("UTF-8")));
            dataOutputStream.flush();
        } catch (IOException e) {
            handleException(e);
        }
    }
}

問題は、フラッシュが正しく機能していないように見えることです。互いに近い 2 つの文字列を送信すると、サーバーは両方の文字列を含むメッセージを 1 つだけ受信します。呼び出しの間に Thread.sleep(1000) を実行すると、すべてが機能しますが、これは明らかに解決策ではありません。私は何が欠けていますか?

4

3 に答える 3

7

flush()データ パケットが出荷されることを保証するものではありません。TCP/IP スタックは、効率を最大化するために自由にデータをバンドルできます。さらに悪いことに、あなたと目的地の間にはおそらく他の TCP/IP スタックがたくさんあり、それらは同じことを自由に行うことができます.

パケットバンドルに頼るべきではないと思います。データに論理ターミネータ/ディバイダを挿入すると、安全になります。

于 2009-12-05T13:49:23.677 に答える
3

データがどのようにパケットに分割されるかについて心配する必要はありません。

メッセージに文字列の長さを含める必要があります。受信側では、最初に長さを読み取ります。たとえば、送信するには

byte[] arbytes = ar.getBytes(Charset.forName("UTF-8"));
output.writeInt(arbytes.length)
output.write(arbytes)

そして、あなたのリーダーであなたはそうします

byte[] arbytes = new byte[input.readInt()];
for(int i = 0; i < len; i++){
     arbytes[i] = input.read();
}
//convert bytes back to string.

read 関数は必ずしも配列の全長を読み取るとは限らないため、input.read(arbytes) を呼び出すことはできません。一度にチャンクを読み取るループを実行できますが、そのコードはもう少し複雑です。

とにかく、あなたはアイデアを得る。


また、どのパケットに何が入るかを本当に制御したい場合は、 Datagram Socketsを使用できますが、そうすると、パケットの配信は保証されません。

于 2009-12-05T14:46:02.930 に答える
1

ソケットは、メッセージではなくデータのストリームを送信します。受信したパケットが送信されたものと同じサイズであることに依存しないでください。ご覧のとおり、パケットはグループ化できますが、分割することもできます。ブロックが送信されたときと同じようにブロックを取得する方法については、@ChadOkereの提案を使用してください。

ただし、あなたの場合は、

dataOutputStream.writeUTF(ar); // sends a string as UTF-8

String text = dataInputStream.readUTF(); // reads a string as UTF-8
于 2009-12-06T08:53:36.170 に答える