Estoy programando un juego multijugador y estoy teniendo dificultades con el tamaño de los paquetes udp. Quiero enviar múltiples estadísticas enemigas (hp, position, id) a través de paquetes udp. Aquí está la parte importante del código:

Byte[] datagramPacketData = ("11" + String.valueOf(entityAmount) + "," + gamename + "," + username + entitiesToBeSent).getBytes();

Como puede ver, estoy fusionando todos los datos en una cadena y luego los convierto en bytes [] antes de enviarlos. Pero los caracteres consumen muchos más bytes que los pequeños ints (para id y posición) y longs (hp). Por ejemplo: una mafia tiene 2.000.000 hp. ese número consumirá 7 caracteres (= 7 bytes), pero solo necesitaría 4 bytes durante mucho tiempo. ¿Cómo puedo enviar todos estos datos usando menos bytes, sin usar flujos de objetos?

¡Estaría muy feliz con algunas sugerencias! Muchas gracias por adelantado.

0
Madness 14 ene. 2017 a las 03:34
¿Convertir cada fragmento individual en bytes en lugar de convertirlos en cadenas y luego todos en bytes a la vez?
 – 
Natecat
14 ene. 2017 a las 03:38
Entonces, ¿cómo los analiza en el lado receptor? Quiero decir, ¿cómo puedo saber qué fragmento de bytes es qué? Porque recibiré solo un byte [] mesh
 – 
Madness
14 ene. 2017 a las 03:40
1
Hay varias cosas que puede hacer. Puede hacer un paquete de longitud estándar para que los rangos de posiciones en la matriz de bytes se correspondan con ciertas variables de manera consistente, o podría agregar bytes a la matriz que le indique la posición del inicio de cada variable, etc.
 – 
Natecat
14 ene. 2017 a las 03:44
Ahh buena idea! :) Creo que me ceñiré a tu primera sugerencia. Muchas gracias, creo que puedo resolver esto ahora :) ¡cuídate amigo!
 – 
Madness
14 ene. 2017 a las 03:47

2 respuestas

En primer lugar, siempre que sus datos sean lo suficientemente pequeños como para caber en un solo paquete, es poco probable que la longitud del mensaje UDP marque una gran diferencia. Le recomendaría que no se preocupe por el tema a menos que tenga evidencia concreta de que el tamaño del paquete es un problema crítico; es decir, resultados duros de evaluación comparativa que muestran que no podrá mantener la velocidad de transmisión mínima requerida por el juego por encima de un cierto tamaño de paquete. (Optimizar para un problema que en realidad no existe es una pérdida de esfuerzo).

Si le preocupa la longitud del mensaje, debería comparar el uso de codificación de cadena (como se indica arriba) y codificación binaria; p.ej. como lo haría con DataInputStream y DataOutputStream.

  • un byte se codificará como un solo octeto
  • un short o char se codificará como dos octetos
  • etcetera.

Consulte los DataOutputStream javadocs para detalles.

No utilice secuencias de objetos. Usan la misma codificación binaria que DataOutputStream, pero hay gastos generales adicionales significativos para codificar la información de tipo y las identidades de objeto.

0
Stephen C 14 ene. 2017 a las 03:57
¡gracias! :) Pasaré de la codificación de cadenas a la codificación binaria, ¡eso debería resolver mi preocupación! :)
 – 
Madness
14 ene. 2017 a las 03:53
Pero primero verifique que su preocupación esté bien fundada. Si no es así, su cambio no hará ninguna diferencia. Será una pérdida de tiempo.
 – 
Stephen C
14 ene. 2017 a las 03:57

Hice mi intento ahora y funciona para String, pero no por mucho tiempo. No puedo entender el error por mi cuenta, ¿tal vez alguno de ustedes pueda encontrar el error? Aquí es:

Del lado del remitente:

byte[] data = new byte[1024];
        int i = 0;

        String packetNumber = "25";

        ByteBuffer buffer0 = ByteBuffer.allocate(2);
        buffer0.put(packetNumber.getBytes());
        byte[] numberInByte = buffer0.array();

        int x = 0;
        for (int k = i; k < numberInByte.length; k++) {
            data[k] = numberInByte[x];
            x++;
            i++;
        }

        long life = 2000000;

        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
        buffer.putLong(life);
        byte[] lifeInByte = buffer.array();

        x = 0;
        for (int k = i; k < lifeInByte.length; k++) {
            data[k] = lifeInByte[x];
            x++;
            i++;
        }

En el lado del receptor:

ByteBuffer byteBuffer = ByteBuffer.wrap(data);

        byte[] packetNumber = new byte[2];
        byteBuffer.get(packetNumber);
        System.out.println(new String(packetNumber));

        long life = byteBuffer.getLong();
        System.out.println(life);

El resultado es: 25 (que es correcto) 1966080 (que no es del todo 2000000, pero ¿por qué?)

0
Madness 14 ene. 2017 a las 04:40
Utilice DataOutputStream + ByteArrayOutputStream, etc. Es más sencillo.
 – 
Stephen C
14 ene. 2017 a las 09:20