Foros del Web » Programación para mayores de 30 ;) » Java »

length en un solo byte

Estas en el tema de length en un solo byte en el foro de Java en Foros del Web. Hola, una pregunta muy tonta :P Tengo muchas variables byte[] y necesito concatenarlas a un nuevo byte[]. Como no se pueden sumar variables de ese ...
  #1 (permalink)  
Antiguo 25/08/2008, 16:42
 
Fecha de Ingreso: marzo-2008
Mensajes: 237
Antigüedad: 16 años, 1 mes
Puntos: 6
length en un solo byte

Hola, una pregunta muy tonta :P

Tengo muchas variables byte[] y necesito concatenarlas a un nuevo byte[]. Como no se pueden sumar variables de ese tipo, las convierto a string y el string final (concatenacion de todos los strings) hago getBytes. Eso creo que funciona (no lo probe, si esta mal diganme xd).

El tema es que hay un problema.
Entre todos los bytes que debo concatenar, hay una variable de tipo byte (no byte[], solamente byte), y esa variable contiene el length de un string :

byte pstrlen = (byte)pstr.length();

Lo que debo concatenar de esa parte es solamente un byte. Si el length que devuelve un int lo convierto a string me devuelve 2 bytes (porque el length es precisamente 19. osea "19" son 2 bytes, 1 byte por char, cierto?). OK, necesito que sea solo un byte lo que se concatene.....

no puedo crear la variable de byte[1] porque castear un int a byte[] no se puede.

Alguien sabe como es esta tonteria? jejej gracias
  #2 (permalink)  
Antiguo 25/08/2008, 17:03
 
Fecha de Ingreso: marzo-2008
Mensajes: 237
Antigüedad: 16 años, 1 mes
Puntos: 6
Respuesta: length en un solo byte

Se me ocurrio otra aclaracion por si no se entiende, yo necesito que el total de bytes sea 21. (el getBytes FINAL).
tengo un string de 20 caracteres, si hago el getBytes me da 20 bytes.
y tengo un byte variable; que debe contener el length de ese string.

OK, esa variable no la puedo convertir de int a string por lo que dije (pq el final sino seria 22 bytes no 21).... entonces? como hacer?
el final de getBytes() debe ser de 21 bytes.
  #3 (permalink)  
Antiguo 26/08/2008, 14:18
 
Fecha de Ingreso: marzo-2008
Mensajes: 237
Antigüedad: 16 años, 1 mes
Puntos: 6
Respuesta: length en un solo byte

nadie?asdsdasdasd
  #4 (permalink)  
Antiguo 26/08/2008, 14:40
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 3 meses
Puntos: 260
Sonrisa Respuesta: length en un solo byte

Hola,

Posiblemente puedas tener problemas al convertir un byte[] a String, si lo que hay en el byte[] son datos binarios. Y dependiendo del charset, pos ejemplo de la conversión de Unicode a ASCII.

Para trabajar con byte[] usa un buffer de bytes, como por ejemplo:

java.io.ByteArrayInputStream
java.io.ByteArrayOutputStream

Saludos,

ps:

byte pstrlen = (byte)pstr.length();
Si length() es de tipo Integer, usa 4 bytes y vas a tener una perdida de exactitud.
byte = 1 byte
Integer = 4 bytes.
  #5 (permalink)  
Antiguo 26/08/2008, 15:39
 
Fecha de Ingreso: marzo-2008
Mensajes: 237
Antigüedad: 16 años, 1 mes
Puntos: 6
Respuesta: length en un solo byte

Si, los datos vendrian a ser binarios. El tema es que no me puedo exceder de los bytes permitidos. Precisamente estoy haciendo un handshake a un peer (protocolo de bittorrent, no importa si no se entiende, este es un problema de Java no del protocolo).

y el protocolo me dice exactamente:

Código:
  Handshake

The handshake is a required message and must be the first message transmitted by the client. It is (49+len(pstr)) bytes long.

handshake: <pstrlen><pstr><reserved><info_hash><peer_id>

    * pstrlen: string length of <pstr>, as a single raw byte
    * pstr: string identifier of the protocol
    * reserved: eight (8) reserved bytes. All current implementations use all zeroes. Each bit in these bytes can be used to change the behavior of the protocol. An email from Bram suggests that trailing bits should be used first, so that leading bits may be used to change the meaning of trailing bits.
    * info_hash: 20-byte SHA1 hash of the info key in the metainfo file. This is the same info_hash that is transmitted in tracker requests.
    * peer_id: 20-byte string used as a unique ID for the client. This is usually the same peer_id that is transmitted in tracker requests (but not always e.g. an anonymity option in Azureus). 

In version 1.0 of the BitTorrent protocol, pstrlen = 19, and pstr = "BitTorrent protocol".
Yo, actualmente en el codigo de Java tengo esto:

String pstr = "BitTorrent protocol";
String pstrlen = "19";
String reserved = "00000000";
String info_hash = "D027FE403E861F4F65F6";
String peer_id = "-AZ2837465019234856-";

String datasendpeer = pstr + pstrlen + reserved + info_hash + peer_id;
salida1.write(datasendpeer.getBytes());


Toda la informacion es correcta. Y fijate que le envio los bytes de todo eso (la idea es hacer todo con binario), pero no recibo respuesta (retorna -1), es claro que es porque le estoy mandando algo mal.
Segun esa especificacion que mostre ahi, lo que dudo es del pstrlen porque al obtener los bytes de eso me devuelve 2, y el protocolo dice claramente que debe ser 1 byte (string length of <pstr>, as a single raw byte).

Porque vos dirias que me serviria una conversion de Unicode a ASCII ? me podrias mostrar un ejemplo en 2 lineas de lo que hablas? ando perdido :(
Del resto no dudo porque cumple con los bytes que dice (creo, jejej), por ejemplo info_hash y peer_id son 20 bytes (porque son 20 chars) y cumple con lo que dice, a lo mismo que reserved.
Lo que tiene que quedar son bytes long de 49+len(pstr)... el 49 ya lo tengo, tengo problemas con el length.. nose si con alguno mas, quizas es posible :S

Última edición por razer; 26/08/2008 a las 15:47
  #6 (permalink)  
Antiguo 26/08/2008, 18:44
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 3 meses
Puntos: 260
Sonrisa Respuesta: length en un solo byte

Cita:
Iniciado por razer Ver Mensaje
Segun esa especificacion que mostre ahi, lo que dudo es del pstrlen porque al obtener los bytes de eso me devuelve 2, y el protocolo dice claramente que debe ser 1 byte (string length of <pstr>, as a single raw byte).
El problema es que el Integer de Java es de 4 bytes.
Es seguro que te pide la longitud en binario. Por lo tanto, si tiene 20 letras ... no mandas '2'+'0'.

Para convertir un Integer en Byte usa java.lang.*
java.lang.Integer.byteValue()

Pero va a ver una perdida de exactitud si hay más de 127 letras (El byte más grande puede ser 127).
Si tuvieras una cantidad de bytes > 127 y mandas length = 127 al protocolo no le va a gustar.

Cita:
Iniciado por razer Ver Mensaje
Porque vos dirias que me serviria una conversion de Unicode a ASCII ?
No, al contrario ... al hacer String.getBytes() ó new String(bytes[]), puedes tener problemas. La documentación dice que la conversión de ese tipo de hace a traves de un Encoder ... que puede cambiar los bytes[]. Específicamente indica que después de la conversión la cantidad de bytes[] puede ser diferente a la longitud del String. Me estoy inmaginando que el servidor te devuele un info_hash, si el servidor lo envio en ANSI y lo metes en un String Unicode, creo que puede tener errores facilmente.

Cita:
Iniciado por razer Ver Mensaje
Del resto no dudo porque cumple con los bytes que dice (creo, jejej), por ejemplo info_hash y peer_id son 20 bytes (porque son 20 chars) y cumple con lo que dice, a lo mismo que reserved.
Lo que tiene que quedar son bytes long de 49+len(pstr)... el 49 ya lo tengo, tengo problemas con el length.. nose si con alguno mas, quizas es posible :S
Tendrías que ver los bytes reales.
Usa la clase java.io.ByteArrayOutputStream
  #7 (permalink)  
Antiguo 26/08/2008, 19:49
 
Fecha de Ingreso: marzo-2008
Mensajes: 237
Antigüedad: 16 años, 1 mes
Puntos: 6
Respuesta: length en un solo byte

Siempre el length va a ser de 19, asi que no va a haber problema creo.
Ya pude convertir el Int del length a byte[] (me baje una funcion), ahora lo que resta es hacer eso con el resto....

yo no sabia que el getBytes() podria llegar a tener errores, lo que intente hacer es esto:

Código:
ByteArrayOutputStream Pepe234 = new ByteArrayOutputStream();
String pstr = "BitTorrent protocol";
String reserved = "00000000";
String info_hash = "D027FE403E861F4F65F6"; 
String peer_id = "-AZ2837465019234856-";
		
Pepe234.write(intToByteArray(pstr.length()));
Pepe234.write(reserved.getBytes());
Pepe234.write(info_hash.getBytes());
Pepe234.write(peer_id.getBytes());
   
salida1.write(Pepe234.toByteArray());
Estoy intentando hacer lo que me decis, hacerme un buffer en memoria y guardar todo (NO, en realidad NO ESTOY haciendo un buffer, para eso hay que usar BufferedByteArrayOutputStream o algo asi no? estoy en bolainas xD) El tema es que me sigue devolviendo -1, pero hay 2 cosas:

No se como obtener los bytes de un String si no es con getBytes (quiza el error venga por ahi porque me dijiste que puede llegar a hacer conversiones mal).
Tampoco se si esas declaraciones de strings estan bien, quizas se deberia hacer de byte de una, verdaderamente ya estoy mareado.....
Y la otra bueno, es segun la especificacion nose si estoy cumpliendo, el pstrlen single byte nose a donde anda pero bueno :P

Es facil pero me estoy enredando solito :(

Última edición por razer; 26/08/2008 a las 19:56
  #8 (permalink)  
Antiguo 26/08/2008, 21:58
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 3 meses
Puntos: 260
Sonrisa Respuesta: length en un solo byte

Ok, voy a tratar de ser breve....

La función intToByteArray() que bajaste, no se si te genera 4 o 1 byte.
En un mensaje anteior escribiste que tenía que ser específicamente 1 solo byte.

La idea de usar ByteArrayOutputStream() era eliminar el String.getBytes().
Lo que quiero darte a entender es simplemente que no puedes confiar que String.getBytes() te va a funcionar siempre igual en todos los sistemas con diferentes codificaciones de caracteres (windows-1252, utf-8, etc).

System.out.println(java.nio.charset.Charset.defaul tCharset().displayName());

Lo más sencillo para asegurarte qué datos estás enviando al servidor es escribirlo en un archivo binario en el disco; abrirlo y comprobar con un editor hexadecimal, que fué lo generado realmente.

java.io.FileOutputStream o = new java.io.FileOutputStream("archive.bin");
o1.write(unicode.getBytes());

La función getBytes() va a convertir de UTF-16 a la codificación que tengas por defecto, como por ejemplo windows-1252. Si el servidor que estas conectado espera ANSI o ASCII posiblemente debería funcionar bien. Pero si el tu tienes otra codificación de caracteres o el servidor espera otra cosa, entonces no va a funcionar.

Espero haber sido de alguna ayuda,
Saludos.
  #9 (permalink)  
Antiguo 27/08/2008, 14:52
 
Fecha de Ingreso: febrero-2006
Mensajes: 35
Antigüedad: 18 años, 3 meses
Puntos: 0
Respuesta: length en un solo byte

Te dejo un ejemplo de como podrias hacer el paquete:
import com.outbackinc.util.log.SysInfo;


public class HandShake {
public static void main(String args[]){
/**Vector de byter que voy a utilizar como paquete que va a tener un
* tamaño total de 68 byte:
* pstrlen: string length of <pstr>, as a single raw byte
* pstr: string identifier of the protocol 19
* reserved: eight (8) reserved bytes. All current implementations use all zeroes. Each bit in these bytes can be used to change the behavior of the protocol. An email from Bram suggests that trailing bits should be used first, so that leading bits may be used to change the meaning of trailing bits.
* info_hash: 20-byte SHA1 hash of the info key in the metainfo file. This is the same info_hash that is transmitted in tracker requests.
* peer_id: 20-byte string used as a unique ID for the client. This is usually the same peer_id that is transmitted in tracker requests (but not always e.g. an anonymity option in Azureus).
*/
byte[] b = new byte[68];


/**Variables en String*/
String pstr = "BitTorrent protocol";
String reserved = "00000000";
String info_hash = "D027FE403E861F4F65F6";
String peer_id = "-AZ2837465019234856-";
String resto = pstr+reserved+info_hash+peer_id;

/**el primer byte es el tamaño de pstr*/
b[0] = (byte) pstr.length();
/**Luego voy guardando cada char en un byte*/
for(int i=0;i<resto.length();i++){
b[i+1] = (byte)resto.charAt(i);
}
/**Muestro los datos para ver si son correctos*/
for(int i=0;i<68;i++){
/**Como el 1 byte tiene que interpretarse como int lo casteo como tal*/
if(i==0)
System.out.println("Resultado: "+(int)b[i]);
else
System.out.println("Resultado: "+(char)b[i]);
}
/**Por ultimo queda enviar con el metodo write(byte[]b) que tiene la clase Socket*/
}
}
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 20:58.