Enviar class por socket send windows

Iniciado por patilanz, 26 Mayo 2014, 07:57 AM

0 Miembros y 1 Visitante están viendo este tema.

patilanz

Hola estoy haciendo un chat en consola con c++ en windows pero quiero enviar una clase msg que contiene el tiempo el usuario y el msg.


Código (cpp) [Seleccionar]
class msg{
public:
msg(){};
msg(string n,string m,time_t t=time(0)){
name=n;
r_msg=m;
tim=t;
};
string getName(){return name;}
string getR_msg(){return r_msg;}
time_t getTime(){return tim;}

private:
string r_msg;
time_t tim;
string name;
};


Ahora quiero enviar la con send(); Pero también quiero mandar un código de mensaje. Lo intente convirtiendo la clase msg en char * moviendo lo 1 char para delante para poder poner el código del msg. Pero son demasiadas conversiones y al final el resultado no fue lo que esperaba. Luego intente crear esta clase:

Código (cpp) [Seleccionar]
#include "stdafx.h"
#ifndef CONECTION_MSG_CPP
#define CONECTION_MSG_CPP
template <typename t>
class connection_msg{
public:
connection_msg(int cod,t cl){
code=cod;
clas=cl;
}
int getCode() const {return code;};
private:
int code;
t clas;
};

#endif

El t es la clase que quiero mandar pero el problema aquí es que lo convierto a char* pero luego para convertirlo otra ves a la clase connection_msg me pide el tipo t que no se sabe.

Alguna idea ?

Saludos

eferion

Por un socket no se puede "enviar" una clase a lo bestia.

El motivo es que sus miembros, por ejemplo la clase string, gestionan memoria dinámica, por lo que si envías una clase "a pelo" la aplicación va a fallar siempre.

Lo que tienes que hacer es "serializar" la clase. Serializar es algo común en programación; cuando guardas una clase en un archivo la estás serializando.

Obviamente no hay una única forma de serializar los datos, depende del uso posterior que se les vaya a dar.

En el caso de las redes, la mejor opción es valerse de algún protocolo a nivel de aplicación para gestionar el serializado. Algunos ejemplos de estos protocolos son: Json, Protocol buffers, XDR, ASN.1

Estos protocolos no son parte del estándar de C++, para poder usarlos tendrás que bajarte alguna librería que los implemente o currarte tu propia implementación. La ventaja es que encontrarás librerías para la gran mayoría de los lenguajes existentes.


x64core

@patilanz:
Podes hacer una estructura predefinida la cual sera compartida por ambos programas e incluyendo toda la información que quieras. para
punteros a memoria serian reemplazados a offsets que junto a la base apuntaran a la cadena que es agrega al final de la estructura
predefinidia, hay muchas posibilidades.

patilanz

Hola gracias a los dos. Ya esta solucionado. Lo que hice fue crear una clase que tiene miembros el codigo del msg y la clase que se va pasar como mensaje. Lo pongo por si alguien quiere ver como es:

Código (cpp) [Seleccionar]
#include "stdafx.h"
#ifndef CONECTION_MSG_CPP
#define CONECTION_MSG_CPP
template <typename t>
class connection_msg{
public:
connection_msg(int cod,t cl){
code=cod;
clas=cl;
}
int getCode() const {return code;}
t getClass() const {return clas;}
private:
int code;
t clas;
};

#endif


Luego cuando envio el mensaje convierto la clase en char* y al recibir la vuelvo a convertir a connection_msg.

Saludos

x64core

Cita de: patilanz en 27 Mayo 2014, 22:25 PM
Hola gracias a los dos. Ya esta solucionado. Lo que hice fue crear una clase que tiene miembros el codigo del msg y la clase que se va pasar como mensaje. Lo pongo por si alguien quiere ver como es:

Código (cpp) [Seleccionar]
#include "stdafx.h"
#ifndef CONECTION_MSG_CPP
#define CONECTION_MSG_CPP
template <typename t>
class connection_msg{
public:
connection_msg(int cod,t cl){
code=cod;
clas=cl;
}
int getCode() const {return code;}
t getClass() const {return clas;}
private:
int code;
t clas;
};

#endif


Luego cuando envio el mensaje convierto la clase en char* y al recibir la vuelvo a convertir a connection_msg.

Saludos
Eso estaria bien para clases que no contiene punteros a memoria dinamica o la mayoria de punteros a memoria, pero a pesar de eso
yo no recomiendo tener un habito de pasar clases entre programas de esa manera es muy inseguro.


patilanz

Hola si no paso los datos así. Como serian los offset ? Crear una variable int que contiene el offset de los punteros o como?  Y el offset de un puntero es el lugar donde acaba?

Gracias

eferion

Yo te dí una solución... aunque no le hayas prestado mucha atención:

XDR, Protocol buffers, Json...

Tutorial protocol buffers

Ejemplos con JSon

Estos protocolos que te comento son a nivel de aplicación, su utilidad es que te permiten enviar cualquier tipo de información sin importar el lenguaje o el sistema sobre el que esté corriendo el ejecutable. Te abstraes de punteros, referencias y particularidades del lenguaje.

Esto se consigue a costa de añadir una capa más a tu código. Puedes conseguir lo mismo escribiendo tú mismo los datos a enviar, pero ahí tendrás que lidiar con los datos tanto en el lado del cliente como en el del servidor.

x64core

Cita de: patilanz en 28 Mayo 2014, 07:50 AM
Hola si no paso los datos así. Como serian los offset ? Crear una variable int que contiene el offset de los punteros o como?  Y el offset de un puntero es el lugar donde acaba?

Gracias
La base + offset apuntarian a la cadena dentro de la estructura enviada.
otra manera seria declara un entero que contenga el numero de cadenas y una variable de tipo cadena, deben ser ultimos
miembros de preferencia luego escribir al final de la estructura todas las cadenas que necesites, al recibir, validar el numero
de cadenas e ir atravez de la cadena. Cada cadena se distingira por el null y para saber el numero de cadenas y no acceder
a memoria invalida seria el miembro que contendra el numero de cadenas.

patilanz

Hola eferion sin me fije en tu respuesta pero al principio me parecio algo mas de trabajo si podias simplemenet usar char* pero luego me di cuenta de que necesitas lo que me dijiste. Vi tus links y se ve muy interesante.

x64Core voy a probar lo que me dijiste a ver que tal.

Pero creo que voy a utilizar json aunque quiero aprender el protocol buffer.

eferion

Obviamente implementar un mecanismo de este tipo lleva algo más de trabajo y tiempo que enviar las cosas "a pelo". Lo que sucede es que si luego quieres comunicar, por ejemplo, una aplicación en C++ con otra en Java, lo mismo tienes que acabar haciendo chapucillas manuales para que la comunicación pueda realizarse satisfactoriamente... utilizando un protocolo a nivel de aplicación evitas este tipo de problemas.

La ventaja de hacer uso de un protocolo de este tipo ya existente es que, por un lado, ya están probados y, por otro, es más fácil encontrar librerías para los diferentes lenguajes y arquitecturas.

Piensa que a la hora de diseñar estos protocolos ya se tuvieron que pegar con el envío de objetos, punteros y referencias... todo eso lo tienes cubierto.