erkosone wrote:@CicTEc si tio, en parte es lo que hablamos de encapsular datos en un int, pero no terminé de entender como encapsular datos byte en un int, la primera parte de la encapsulacion que es del cliente hacia el servidor ya está hecha, son boolean en un INT32, ahora me liaré a usar un int como un array de 4 bytes, con eso voy a ahorrar un monton mas de ancho de banda.
Bien, es mejor como sistema de transmision de datos.
erkosone wrote:Al final te hice caso y he dejado de lado los String como contenedor de datos, son demasiado pesados y por algun motivo que desconozco son mas propensos a corromperse viajando por UDP que los propios INT
Me alegro que te haya servido.
Aunque no te recomiendo usar el sistema STRING, asi por curiosidad, como enviabas esto dato STRING por la red ? de aqui se podria entender del porque te da error.
erkosone wrote:así que intento solo usar INT en las transmisiones para mantener una coherencia en el memory alloc y así facilitar los saltos por la memoria en los bucles que descomponen los datagramas en propiedades de los objetos. Osea que me llega al cliente una trama de datos tal como esta:
char int int int int int int int int int int int int.......
El char/byte inicial me indica que hacer con los datos, por ahora estos son los comandos que estoy usando por red mediante este char/byte:
/* NET COMMANDS */
final char NET_LOGIN = 'a';
final char NET_PLAYER_CONTROLS = 'b';
final char NET_LOGOUT = 'c';
/* SERVER NET COMMANDS */
final char NET_KICK = 'd';
final char NET_PARAMS = 'e';
final char NET_LOGIN_OK = 'f';
final char NET_LOGIN_ACCOUNT_NOT_EXISTS = 'g';
final char NET_CREATE_ACCOUNT = 'h';
final char NET_NICKNAME_ALREADY_IN_USE = 'i';
final char NET_OBJ_PLAYER = 'j';
final char NET_OBJ_STREAM = 'k';
final char NET_LOGIN_INCORRECT_PASSWORD = 'l';
final char NET_SET_GAME_ZONEMAP = 'm';
final char NET_PING = 'n';
Y en el INT32 [] me llegan los datos de los objetos de esta forma:
int type;
int x;
int y;
int id;
int crc;
Y lo que hago para asegurarme de que el protocolo UDP no me provoca parpadeos o posicionamientos anomalos es enviar al cliente desde el servidor la X la Y y el ID del objeto, su tipo, y finalmente la suma de todos estos parametros, y en el cliente lo que hago es leer los parametros y sumarlos, y luego los comparo con el ultimo llamado 'CRC', si coincide es que la información es integra, si no coincide está corrupta.
Bueno.. por ahora todo marcha, avanzo despacio por que quiero por lo menos tener una base solida, soy muy maniatico con esto.
Y ya te digo, tengo que mirar como encapsular un array de byte´s en un int y podre mejorar la comunicacion bastante mas.
Recuerda que CHAR en java no es byte, es short, java usa este tipo de datos para la codificacion de caracteres de texto, y la codificacion de las cadenas de texto usada es UTF-8 con lo cual cada char son 16bits, o sea equivalente a 2 bytes.
Dicho esto, la codificacion de bytes en un int es sencilla, primero pero debes asegurarte que INT sea efectivamente 32bit y que no cambie de dimencion segun la plataforma/architectura en la cual es enviado, sino vas a tener problemas de procesamiento de los datos.
Establechedo que el INT es siempre 32bits, esto lo puedes tomar igual a la codificacion de un color RGBA (32bit) donde cada canal son 8bits.
Suponendo que el endianess de la plataforma es little donde los bits se leen dal menos significativo (empezando por el ultimo a la derecha) hacia el mas significativo (el primero a la izquierda), o sea 31.....0, la codificacion de un RGBA seria...
INT =
A R G B, repartido:
A = bit
24 a 31, mascara de bit para obtener el valor =
0xFF000000, shifting de desplazamiento para el desempaquetado =
>> 24, shifting de desplazamiento para el empaquetado =
<< 24 R = bit
16 a 23, mascara de bit para obtener el valor =
0x00FF0000, shifting de desplazamiento para el desempaquetado =
>> 16, shifting de desplazamiento para el empaquetado =
<< 16G = bit
8 a 15, mascara de bit para obtener el valor =
0x0000FF00, shifting de desplazamiento para el desempaquetado =
>> 8, shifting de desplazamiento para el empaquetado =
<< 8B = bit
0 a 7, mascara de bit para obtener el valor =
0x000000FF, o simplemente 0xFF, shifting de desplazamiento para el desempaquetado =
niguno, shifting de desplazamiento para el empaquetado =
nigunoCon estas reglas y datos puedes extraer bytes de cualquier INT y/o empaquetarlas en otro.
Ahora ponemos un ejemplo, tienes una variable llamada "color" que es INT 32bit y le quieres guardar un color equivalente a una llamada ARGB = 255, 128, 64, 32, tendras la variable "visualmente" asi:
color = 255|128|64|32Ahora tienes 4 variables byte llamadas R, G, B, A, para memorizar en cada una el correspondiente canal-byte del color seria:
A = (color & 0xFF000000) >> 24; (mascara + desplazamiento para desempaquetado)
R = (color & 0x00FF0000) >> 16;
G = (color & 0x0000FF00) >> 8;
B = (color & 0x000000FF);Operacion inversa (empaquetado en un INT) en una variable "new_color" de tipo INT partendo da las variables canal-bytes:
new_color = (G << 8); (la mascara no es necesaria en el empaquetado, solo en el desempaquetado)
La istruccion anterior pone el estado de la variable "visualmente" asi:
new_color = 0|0|64|0Para empaquetar mas valores simultaneamiente se usa el operador suma ("+") o mas propriamente el operador bit a bit "|" (OR).
Ejemplo 1: la variable "new_color" esta nuevamente vacia (0) y queremos empaquetar los caneles R y G, seria:
new_color = (R << 16) | (G << 8); (datos byte + valores de desplazamiento para empaquetado conjuntos con el operador bit a bit "|")
La istruccion anterior pone el estado de la variable "visualmente" asi:
new_color = 0|128|64|0Ejemplo 2: tenendo "new_color" en el estado seteado del ejemplo 1 y querendole ahora empaquetar tambien el valor A, seria:
new_color = (A << 24) | (new_color);La istruccion anterior pone el estado de la variable "visualmente" asi:
new_color = 255|128|64|0Ejemplo 3: tenendo "new_color" en el estado seteado del ejemplo 2, y querendole modificar el valor de A da 255 a 128, ponendo el caso de tener otra variable byte "A_50p" la operacion seria la siguiente:
new_color = (A_50p << 24) | (new_color & 0x00FFFFFF);La istruccion anterior pone el estado de la variable "visualmente" asi:
new_color = 128|128|64|0Notaras en este ultimo ejemplo la mascara 0x00FFFFFF, si te fijas esta es la conjuncion de las mascaras para los canales R, G y B, el motivo es que cuando se sobreescribe un valor no "vacio" (en el caso anterior A no es mas 0, sino 255) es necesario obtener un nuevo dato temporal con el byte vacio, eso se hace con la mascara, que recupera los datos R G B tal cual estan y setea el A a 0 (lo limpia) para luego escribir el nuevo valor.
Esto es todo, basandote en estas reglas y ejemplos te puedes montar el sistema de empaquetado/desempaquetado de bytes en INT.