Помещение короткого замыкания в 2 байта строки - PullRequest
3 голосов
/ 28 октября 2011

Итак, я создаю собственный сетевой протокол для онлайн-игры, чтобы сэкономить место, каждому сообщению (отправляемому по TCP) присваивается короткий идентификатор, 2 байта, все сообщения, отправляемые с сервера клиенту и т. Д.И наоборот, это строки, как я могу преобразовать короткую строку в Java всего за 2 байта (символа)?

Обновление: Я, вероятно, не совсем понимаю, что я хочу... Я хочу иметь возможность преобразовать короткое int в 2 символа, чтобы я мог отправить короткое по сети в строковом формате всего за 2 байта и декодировать его обратно в короткое с другой стороны (в ActionScript 3).

Символ может содержать 256 возможных значений, верно?Итак, 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 символа, и он может быть коротким.

Ответы [ 3 ]

6 голосов
/ 28 октября 2011

Это можно сделать для некоторого значения «возможно».

String s = "" + (char)myShort;

Однако , результирующая строка может быть недействительной, так как не все 16-битные целые числа представляют действительные (кодированные в UTF-16) кодовые точки! То есть результирующая строка может быть неверной последовательностью UTF-16. Различные строковые функции и / или кодирование / декодирование могут привести к «странному поведению» , поскольку основные правила были нарушены (я думаю, что что-то может произойти, но это немного слабо для , но. ..). Вы были предупреждены - см. Нижний пример, показывающий только одно возможное проявление.

Т.Л., др. Не использовать строки для такой передачи по сети *. Скорее, использует байтовые массивы (или ByteBuffers) и отправляет шорт в виде двух октетов, старшего и младшего. (О, и я упоминал 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!!!!!
1 голос
/ 28 октября 2011

DataOutputStream.writeShort / DataInputStream.readShort

0 голосов
/ 28 октября 2011

Я не использую Java, но я думаю, что вы просто хотите использовать оператор приведения.Если ваше короткое называется mynumber, используйте (char) mynumber.То есть, если вы собираетесь обрабатывать эти биты как короткие, когда они выходят на другую сторону.Удачи вам в кросс-платформенности, хотя, если вы используете «short» в качестве определения своего поля, а не «16-битное знаковое int», есть некоторые эзотерические платформы.

...