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

[SOLUCIONADO] obtener longitud de un DatagramPacket recibido

Estas en el tema de obtener longitud de un DatagramPacket recibido en el foro de Java en Foros del Web. Estoy porgramando un servidor TFTP (mas sencillo que el FTP), basandome en estas [URL="http://i.stack.imgur.com/6dTH6.png"]normas de paquetes[/URL] edit: entiendo porque no genera el enlace jeje Mi ...
  #1 (permalink)  
Antiguo 13/03/2016, 12:25
 
Fecha de Ingreso: noviembre-2014
Mensajes: 17
Antigüedad: 9 años, 6 meses
Puntos: 0
obtener longitud de un DatagramPacket recibido

Estoy porgramando un servidor TFTP (mas sencillo que el FTP), basandome en estas
[URL="http://i.stack.imgur.com/6dTH6.png"]normas de paquetes[/URL]
edit: entiendo porque no genera el enlace jeje

Mi probema es que cuando el paquete RRQ del cliente llega al servidor no puedo saber la longitud original del contenido, ya que, cuando llega el paquete tengo que guardarlo en uno predefinido (new DatagramPacket) en la clase server. A este paquete de la clase server le doi un buffer de 516 bytes (o menor, segun la imagen para paquetes de tipo Data son maximo 516 bytes). Entonces cuando hago un datagrampaquet.getLength en el servidor, me da la longitud del paquete que creé en el server no del cliente.

Código:
public void metodoData() throws IOException{
//bufferde bytes para el datagrampacket
byte[] packet = new byte[516];
//modo de trabajo - lo deberia usar en algun momento para restar bytes que no quiero al array de datos
byte binariMode = (byte) "octet".length();
//creamos un socket
DatagramSocket datagramSocket = new DatagramSocket(5000); //mientras reciba while (true) { boolean ackRecibidos=true; int i=0;
//creamos un datagrampacket con el byte[] anteriormete definido
DatagramPacket datagramPacket = new DatagramPacket(packet,packet.length);
//recibimos un paquete
datagramSocket.receive(datagramPacket); System.out.println("servidor: llego un paquete!!:"); //creamos un byte[] de la longitud original del contenido(mentira!!!) byte[] inData = new byte[datagramPacket.getLength()];
//obtenemos los bytes del paquete. Esto me da los bytes que tienen valor mas los nulos del datagrampacket del servidor
inData = datagramPacket.getData(); System.out.println("el fichero mide "+inData.length); // comprobamos si es un paquete RRQ byte code; code = inData[1]; System.out.println("servidor: codigo "+code); //si es una peticion de lectura if (code == RRQ) { System.out.println("servidor: Es un RRQ!!");
//obtengo el nombre del fichero. Este metodo me lo copie de internet. no funciona del todo bien.
String fileName = this.getFileName(inData, inDataLength); System.out.println(fileName); public String getFileName(byte[] inData, ) { byte[] aux = new byte[inData-7]; for (int i = 0; i < aux.length; i++) { aux[i] = inData[i + 2]; } System.out.println("server: el nombre del fichero mire: "+aux.length); return new String(aux); }
Ahora, cuando imprimo el nombre del fichero, me imprime nombre+byteNulos.
Entonces pense, de poner un if que leyera el fileName y al primer byte null que encuentre saliera y devolviera el fileName sin byte nulos, pero no encontre una equivalencia para igualar a bytes nulos.
Si no me explique bien, comenten pls.
Todo esto porque no logro extraer el filename del paquete que llega del cliente
  #2 (permalink)  
Antiguo 13/03/2016, 14:05
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 7 meses
Puntos: 454
Respuesta: obtener longitud de un DatagramPacket recibido

Hola:

Puedes usar byte nulo un byte 0 (es la forma en que C/C++ limitan las cadenas, poniendo un 0 al final de ellas).

O bien, al estilo java, con algo como la clase DataOutputStream y DataInputStream, con los método writeutf() y readutf(). Lo que hacen es escribir primero 2 bytes con la longitud de la cadena y luego la cadena. readutf() hace lo contrario, lee 2 bytes para saber la longitud de la cadena y luego lee una cadena con ese número de bytes.

También suele ser habitual terminar las cadenas con un retonro de carro \n. De esta forma, en la lectura, se puede usar una clase BufferedReader con su método readLine(), que lee la cadena hasta encontrar un retorno de carro.

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #3 (permalink)  
Antiguo 13/03/2016, 15:12
 
Fecha de Ingreso: noviembre-2014
Mensajes: 17
Antigüedad: 9 años, 6 meses
Puntos: 0
Respuesta: obtener longitud de un DatagramPacket recibido

Buena idea, podria incluir un"\n" despues del fileName cuando construya el paquete RRQ en el cliente. Pero a la hora de detectarlo en el array de bytes en el metodo getFileName como lo hago?
Sería facil si tuviera que comparar byte a byte, pero el "\n" ocupa 2 bytes. Hay alguna manera de buscar una sequencia de bytes en un array de bytes?
  #4 (permalink)  
Antiguo 13/03/2016, 15:23
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 7 meses
Puntos: 454
Respuesta: obtener longitud de un DatagramPacket recibido

Hola:

Como te comentaba, un BufferedReader.readLine() lo hace por tí.
De todas formas, un \n es un solo caracter. En windows, los ficheros llevan dos, \r\n, pero el \n en sí, en código, sólo es un byte.

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #5 (permalink)  
Antiguo 13/03/2016, 20:08
 
Fecha de Ingreso: noviembre-2014
Mensajes: 17
Antigüedad: 9 años, 6 meses
Puntos: 0
Información Respuesta: obtener longitud de un DatagramPacket recibido

edit: El contenido de este post no se rige al titulo, pero cumple la finalidad.
GENIAL, funcionó, me extrae el nombre del fichero. Ahora que envie el fichero dividido en paquetes es otra historia.
Dejo aqui el código de getFileName() por si alguien lo quiere :

Código:
public String getFileName(byte[] inData) throws IOException {
//obtenemos un sub-array, desde la pocicion [2] (porque no queremos el opCode) hasta el final de inData
byte[] b =Arrays.copyOfRange(inData, 2, inData.length); InputStream is = new ByteArrayInputStream(b); BufferedReader bf = new BufferedReader(new InputStreamReader(is));
//leemos una palabra que se guardará en cuanto encuentre un "\n" (sumado previamente a la String del nombre del fichero que pide desde la clase cliente)
String filename = bf.readLine(); bf.close(); is.close(); System.out.println("server: el nombre del fichero mide: "+filename.length()); return filename; }
Gracias.

Etiquetas: cliente, servidor, 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 07:59.