Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Protocol Buffers , Sockets

Estas en el tema de Protocol Buffers , Sockets en el foro de C/C++ en Foros del Web. Buenas tardes estoy intentando enviar una estructura de datos mediante sockets entre dos plataformas distintas. El sender esta programado en c++ y el que recibe ...
  #1 (permalink)  
Antiguo 06/06/2016, 08:51
 
Fecha de Ingreso: agosto-2010
Mensajes: 20
Antigüedad: 14 años, 3 meses
Puntos: 0
Protocol Buffers , Sockets

Buenas tardes estoy intentando enviar una estructura de datos mediante sockets entre dos plataformas distintas. El sender esta programado en c++ y el que recibe el mensaje es c#. Para serializar la estructura utilizo Protocol buffers [URL="https://developers.google.com/protocol-buffers/"]https://developers.google.com/protocol-buffers/[/URL]

Si utilizo protocol buffers con archivos en mi ordenador no tengo ningun problema en serializar y deserializar los datos, todo empieza cuando intento enviar esa informacion a traves de un socket. A continuacion os pongo el codigo para que os hagais una idea y luego el error:

C++
Código:
        // Aqui relleno mi mensaje que es exactamente igual que el ejemplo de la pagina oficial.

        tutorial::AddressBook address_book;
	tutorial::Person* person = address_book.add_person();
	person->set_email("abcdefgh");
	person->set_id(13);
	person->set_name("pepito");

        // Serializo el mensaje en un string y lo envio a traves del socket
        
        string buf;
        person->SerializeToString(&buf);
	send(newsockfd,buf.data(),buf.length(), 0);
C#
Código:
        private AddressBook newdata; // esta es la variable donde se va a alojar el mensaje
        ............
        byte[] buffer = new byte[1024];
        int bytes = 0;
        bytes=handler.Receive(buffer);
        newdata = AddressBook.Parser.ParseFrom(buffer);
Una vez aqui...el error que se produce es : Protocol message contained an invalid tag ( zero )

Este error ya me sucedia al leer desde archivos en vez de los sockets y lo solucione creando un array del mismo tamaño que los byes que ocupaba el archivo. Pero el buffer de sockets da igual que le ponga los 24 bytes que se envian que no funciona, sale ese mensaje de arriba. Alguien sabe que estoy haciendo mal?
  #2 (permalink)  
Antiguo 06/06/2016, 09:34
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Protocol Buffers , Sockets

Cita:
bool SerializeToString(string* output) const;: serializes the message and stores the bytes in the given string. Note that the bytes are binary, not text; we only use the string class as a convenient container.
¿Estás seguro de que buf.length() te está dando un valor correcto?

No digo que esté ahí el fallo, pero es por empezar a tirar del hilo.

Un saludo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.

Última edición por eferion; 06/06/2016 a las 10:13
  #3 (permalink)  
Antiguo 06/06/2016, 11:32
 
Fecha de Ingreso: agosto-2010
Mensajes: 20
Antigüedad: 14 años, 3 meses
Puntos: 0
Respuesta: Protocol Buffers , Sockets

Si, es lo mismo. Tanto buf.length() como person->ByteSize() son iguales. 20 bytes exactamente.

Ahora por ejemplo el buffer en el lado de recibir lo he puesto de 20 bytes en vez de 1024 y no da el error pero los datos no estan bien. Las variables name, email estan vacias y el id es 0...

*** EDITO ***

He encontrado un error, es el siguiente. En el codigo de envio estoy serializando un mensaje del tipo PERSON, y en C# estoy deserializando un tipo ADDRESSBOOK, ahora todo llega correctamente, siempre y cuando el buffer en la parte de recibir sea igual al numero de bytes del paquete que se envia. Ahora solo falta tener un buffer que sea igual que el numero de bytes que recibo que es impredecible

Última edición por Ace_Slelt; 06/06/2016 a las 12:22
  #4 (permalink)  
Antiguo 07/06/2016, 01:17
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Protocol Buffers , Sockets

Cita:
Iniciado por Ace_Slelt Ver Mensaje
He encontrado un error, es el siguiente. En el codigo de envio estoy serializando un mensaje del tipo PERSON, y en C# estoy deserializando un tipo ADDRESSBOOK, ahora todo llega correctamente, siempre y cuando el buffer en la parte de recibir sea igual al numero de bytes del paquete que se envia. Ahora solo falta tener un buffer que sea igual que el numero de bytes que recibo que es impredecible
Una corrección al respecto:

El buffer que recibe debería ser al menos tan grande como el mayor paquete que puedes recibir... al menos para empezar. Cuando la comunicación te funcione podrás intentar optimizar ese punto.

Pero entonces no funciona

Cuando tu recibes datos por un socket, un valor que recuperas es el número de bytes recibidos. Lo que has de hacer es usar dicho valor para recuperar únicamente la secuencia serializada y descartar lo que haya en el resto del buffer.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #5 (permalink)  
Antiguo 07/06/2016, 21:06
 
Fecha de Ingreso: agosto-2010
Mensajes: 20
Antigüedad: 14 años, 3 meses
Puntos: 0
Respuesta: Protocol Buffers , Sockets

Cita:
Iniciado por eferion Ver Mensaje
Una corrección al respecto:

El buffer que recibe debería ser al menos tan grande como el mayor paquete que puedes recibir... al menos para empezar. Cuando la comunicación te funcione podrás intentar optimizar ese punto.

Pero entonces no funciona

Cuando tu recibes datos por un socket, un valor que recuperas es el número de bytes recibidos. Lo que has de hacer es usar dicho valor para recuperar únicamente la secuencia serializada y descartar lo que haya en el resto del buffer.

Un saludo.


SOLUCION :

La solucion ha sido crear un buffer como bien indica eferion lo suficientemente grande como para alojar un posible paquete recibido por el socket. Acto seguido creo un nuevo buffer con el tamaño de bytes recibidos por la funcion receive y deserializo el paquete. Importante que el tipo de mensaje de protocol buffers en los dos extremos sea igual, es decir. Si serializo un mensaje de tipo, me lo invento, receta....he de deserialziar un buffer de tipo receta, no cantidad de sal como estaba haciendo.

C#

Código:
        private AddressBook newdata;
        ....
        // Creo un array lo suficientemente grande para recibir los datos del socket.

        byte[] buffer = new byte[1024]; 
        int bytes = 0;
        bytes = handler.Receive(buffer);
        
        // Creo un segundo array exactamente igual de largo que el paquete recibido.

        byte[] buffer2 = new byte[bytes];
        Buffer.BlockCopy(buffer, 0, buffer2, 0, bytes);
        newdata = AddressBook.Parser.ParseFrom(buffer2);
C++
Código:
        // Aqui relleno mi mensaje que es exactamente igual que el ejemplo de la pagina oficial.

        tutorial::AddressBook address_book;
	tutorial::Person* person = address_book.add_person();
	person->set_email("abcdefgh");
	person->set_id(13);
	person->set_name("pepito");

	
	
        // Serializo el mensaje en un string y lo envio a traves del socket
        
        string buf;
        address_book.SerializeToString(&buf);
	send(newsockfd,buf.data(),buf.length(), 0);

Espero que a alguien le pueda servir de algo!!!

Etiquetas: funcion, int, programa, sockets, variable
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 11:30.