3

So I'm making my own networking protocol for a online game, to save space each message (sent over TCP) is given a ID which is a short, 2 bytes, all messages sent from the server to the client and vice versa are strings, how can I convert a short to a string in java in just 2 bytes (characters)?

Update: I'm probably not being clear as to what I want... I want to be able to convert a short int into 2 characters, so that I can send the short over the network in a string format in just 2 bytes and decode it back into a short on the other side (in actionscript 3).

A character can hold 256 possible values right? So 256*256=65,536 which is the size of a unsigned short int!

Here's what I've got so far:

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
}

This can turn a int into a single character which can be sent over the network, now I just need to have it use 2 characters and it can do up to a short.

James T
  • 3,292
  • 8
  • 40
  • 70

3 Answers3

6

This is possible to do for some value of "possible".

String s = "" + (char)myShort;

However, the resulting string may be invalid as not all 16-bit integers represent valid (UTF-16 encoded) code-points! That is, the resulting string may be an invalid UTF-16 sequence. Various string functions and/or encoding/decode may result in "strange behavior" as the fundamental rules have been violated (I think it is somewhat lax as to what may occur, but...). You have been warned -- see the bottom example showing just one possible manifestation.

tl,dr. Don't use strings for this sort of network transmission*. Rather, use byte arrays (or ByteBuffers) and send the short as two octets, high and low. (Oh, and did I mention ByteBuffers? Take a look at the methods...) If strings need to be sent they can be encoded (UTF-8) and also sent as "bytes" in the data packets.

Of course, it is quite likely be simpler just to use standard Serialization or Protocol buffers to deal with the packets... sure beats custom encoding. (Also, protocol buffers does some neat tricks like zig-zag integer encoding...)

Happy coding :)


*Although, Quake 3 use strings for a number of network messages ... however, it encoded the values "as plain text" -- e.g. "xyz=1234" -- and used a bunch of monkey hand-serialization code.


See the last value in the output as to why this "string stuffing" can be bad stuff ;-)

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

The results in 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!!!!!
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • Oh, please do explain the -1. –  Oct 28 '11 at 04:45
  • I can't use standard Serialization, as the client will be in flash and server in java, so I'd need some custom serialization. – James T Oct 28 '11 at 16:13
  • @Bubby4j In any case, treat the serialization and transmitted data as a sequence of octects, not a string (at least from Java). I am not sure what support Flash has for byte streams or how it handles strings/string decoding. It might be beneficial to just use a "fat" text-based message format (even, say, JSON) which will be "string safe" unless there is a proven need to encode it into something very compact. Other options include base-encoding of binary data (base64 is common but a custom base96/128 is still be UTF-8 friendly; it doesn't have to be a "readable" encoding, just a "valid" one). –  Oct 28 '11 at 18:30
  • @Bubby4j "UTF-8 friendly" strings are those in which all (or almost all) characters can be encoded into a single octet; all regular ASCII characters are encoded as a single octet. –  Oct 28 '11 at 20:42
1

DataOutputStream.writeShort/DataInputStream.readShort?

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • +1 Very good point -- there be relatively simple methods for serialization streams. –  Oct 28 '11 at 20:45
-1

I don't use java, but I think you just want to use a cast operator. If your short is called mynumber, use (char) mynumber. That is, if you then intend to treat those bits as a short when they come out the other side. Good luck with cross-platformness though if you're using "short" as the definition of your field rather than "16-bit signed int", there are some esoteric platforms out there.

Dan
  • 10,531
  • 2
  • 36
  • 55