3

そこで、私はオンライン ゲーム用に独自のネットワーク プロトコルを作成しています。スペースを節約するために、(TCP 経由で送信される) 各メッセージには、短い 2 バイトの ID が与えられます。サーバーからクライアントに、およびその逆に送信されるすべてのメッセージは文字列です。 、Javaで短い文字列を2バイト(文字)で文字列に変換するにはどうすればよいですか?

更新:私はおそらく私が何を望んでいるのかはっきりしていません...短い整数を2文字に変換できるようにしたいので、ネットワーク経由で短い文字列をわずか2バイトの文字列形式で送信し、反対側でショートにデコードします(actionscript 3)。

文字は 256 の可能な値を保持できますよね? したがって、unsigned short int のサイズである 256*256=65,536 です!

ここに私がこれまでに持っているものがあります:

public static String toCode(int c){

    if(c <= 255 ){
        return Character.toString((char)c);
    }else{
        return null;
    }
}

public static int fromCode(String c){
    return ((int)c.charAt(0));//Return the character code of the send string, 1 char only
}

これにより、ネットワーク経由で送信できる単一の文字に int を変換できます。これで、2 つの文字を使用するだけで、最大で short まで実行できます。

4

3 に答える 3

6

これは、「possible」の値に対して実行できます。

String s = "" + (char)myShort;

ただし、すべての 16 ビット整数が有効な (UTF-16 エンコードされた) コードポイントを表すわけではないため、結果の文字列は無効になる場合があります。つまり、結果の文字列は無効なUTF-16 シーケンスである可能性があります。さまざまな文字列関数および/またはエンコード/デコードは、基本的なルールに違反しているため、「奇妙な動作」を引き起こす可能性があります (が起こるかについては多少緩いと思いますが...)。あなたは警告されています -- 可能性のある現象を 1 つだけ示している一番下の例を参照してください。

tl、博士。この種のネットワーク送信には文字列を使用しないでください*。代わりに、バイト配列(または ByteBuffers) を使用し、short を高低の 2 つのオクテットとして送信します。(ああ、ByteBuffersについて言及しましたか? メソッドを見てください...) 文字列を送信する必要がある場合は、文字列をエンコード (UTF-8) し、データ パケットで「バイト」として送信することもできます。

もちろん、標準のシリアライゼーションまたはプロトコル バッファを使用してパケットを処理する方が簡単である可能性が非常に高く、カスタム エンコーディングより確実に優れています。(また、プロトコルバッファは、ジグザグ整数エンコーディングのようないくつかの巧妙なトリックを行います...)

ハッピーコーディング:)


*ただし、Quake 3 は多くのネットワーク メッセージに文字列を使用します...ただし、値を「プレーン テキストとして」エンコードし、たとえば「xyz=1234」と、一連のモンキー ハンド シリアル化コードを使用しました。


この「文字列の詰め込み」が悪いものになる理由については、出力の最後の値を参照してください;-)

public class test1 {
    public static void main (String[] args) throws Exception {
        int s1 = 0xd801;
        short s = (short)s1;
        String x = "" + (char)s;
        System.out.println("orig int: " + s1);
        System.out.println("orig short: " + s);
        System.out.println("length of string: " + x.length());
        System.out.println("value in string: " + (short)x.codePointAt(0));
        int s2 = ((short)x.codePointAt(0)) & 0xffff;
        System.out.println("restored value: " + s2);
        byte[] xb = x.getBytes("UTF8");
        System.out.println("encoded size: " + xb.length);
        String x2 = new String(xb, "UTF8");
        System.out.println("decode:" + x2);
        System.out.println("decode length:" + x2.length());
        int s3 = ((short)x2.codePointAt(0)) & 0xffff;
        System.out.println("value in string:" + s3);
    }
}

JDK 7、Windows 64 での結果。

orig int: 55297
orig short: -10239
length of string: 1
value in string: -10239
restored value: 55297
encoded size: 1
decode:?
decode length:1
value in string:63    WHAT IS THIS?!?!?! NOOOOO!!!!!
于 2011-10-28T04:31:59.123 に答える
1

DataOutputStream.writeShort/DataInputStream.readShort?

于 2011-10-28T09:01:28.700 に答える
-1

私はJavaを使用していませんが、キャスト演算子を使用したいだけだと思います。あなたの略称が mynumber と呼ばれる場合は、(char) mynumber を使用します。つまり、これらのビットが反対側に出たときにショートとして扱う場合です。フィールドの定義として「16 ビットの符号付き整数」ではなく「ショート」を使用している場合は、クロスプラットフォームで頑張ってください。難解なプラットフォームがいくつかあります。

于 2011-10-28T04:27:01.643 に答える