elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Curso de javascript por TickTack


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Sockets y concurrencia, duda básica
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Sockets y concurrencia, duda básica  (Leído 2,880 veces)
mk7

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Sockets y concurrencia, duda básica
« en: 21 Mayo 2014, 13:51 pm »

Buenos días y saludos a toda la gente del foro.

Estoy intentando desarrollar un programa en c++ para windows que se comunique con otro dispositivo (en este caso un móvil) para enviar un array de datos.
El tema es que esos datos representan una imágen RGB24. En el programa, por un lado tengo un hilo que genera esas imágenes en un objeto OniRGB888* textura a una velocidad de 15fps aproximadamente.
En otro hilo quiero coger el frame más nuevo y enviarlo por socket TCP con la frecuencia más rápida que sea posible.
En principio tengo varias dudas. No se ni cual es la mejor forma de enfocar el problema. Había pensado en pasar el array por valor a la función de envío de forma que se haga una copia del array en la pila que no destroce el hilo principal cuando escriba el nuevo frame, pero me parece un poco complicado.
Asi que para empezar me gustaría hacer una versión inicial de un solo hilo que genere el frame y luego lo envíe. No genere el siguiente hasta que termine el envío del primero.
textura es un array de una dimensión con una resolucion de 800x600. Es decir, su tamaño es 800x600x3= nº bytes. Como puedo envíar esto por socket y recibirlo en un programa java. Ya he enviado strings pero en este caso que se enviaría en varios datagramas no tengo ni idea de como hacerlo. A ver si me podeis echar una mano.


En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Sockets y concurrencia, duda básica
« Respuesta #1 en: 21 Mayo 2014, 13:59 pm »

Para enviar datos por red hay, básicamente, dos opciones: TCP y UDP

* TCP es un protocolo "seguro", garantiza una conexión persistente, no se pierden tramas y los datos llegan ordenados...

* UDP es inseguro: no garantiza el estado de la conexión, se pueden perder paquetes y los datos pueden llegar en orden aleatorio. La ventaja es que es bastante más rápido.

En tu caso, lo suyo sería crear una conexión UDP, ya que es más rápida, flexible y eficiente. Implementar un mecanismo simple que te permita descartar imágenes ( por llegar después de otra más actual, por ejemplo ) es bastante sencillo y no sacrificas velocidad.

Ten en cuenta que a la conexión le va a dar igual las prisas que tu tengas, va a su velocidad. Si intentas enviar datos a más velocidad lo único que conseguirás es que se apilen los mensajes en la cola de salida... con la posibilidad de que alguno se pierda.

Para que sistemas diferentes se puedan comunicar entre sí es necesario establecer un protocolo de comunicación que ambos entiendan. Puedes programarte uno o usar uno ya existente. Lo mejor, desde mi punto de vista, es usar uno ya existente. Puedes probar Json, XDR, protocol buffers (google) o ASN.1.




En línea

mk7

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Re: Sockets y concurrencia, duda básica
« Respuesta #2 en: 21 Mayo 2014, 18:03 pm »

Probablemente UDP sea lo más correcto para sacar el máximo rendimiento. Pero teniendo en cuenta que cada frame habría que enviarlo en varios paquetes igual es mucho lio para reconstruirlos en el destino.
La verdad, es que dándote la razón, me gustaría hacer una prueba inicial con TCP a ver que rendimiento resulta.
Los datos a transferir serían bytes. En el destino busco renderizar la imagen RGB24 usando OpenGL. Entonces lo que quiero es reconstruir el array tal cual lo envío en bytes.
OniRGB888* textura es un puntero a una posición de memoria. textura+1 sería el siguiente pixel y cada pixel son 3 bytes (uno por color), por lo tanto, se enviarían 3 bytes cada vez que avanzo el puntero. (Creo no equivocarme).
Y, olvidándonos de momento del tema de los hilos. Aquí es donde no se como tengo que enviar este objeto. Se que el método send me devuelve los bytes enviados y tengo iterar hasta envíar el frame completo. ¿Como le paso al método send la posición de memoria de este objeto?¿Como le digo que vaya en bytes en lugar de 3 bytes?



¿Como puedo saber en el servidor que envía cuando el receptor ha terminado de recibir los datos?
« Última modificación: 22 Mayo 2014, 12:24 pm por Eternal Idol » En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Sockets y concurrencia, duda básica
« Respuesta #3 en: 22 Mayo 2014, 09:52 am »

Pero teniendo en cuenta que cada frame habría que enviarlo en varios paquetes igual es mucho lio para reconstruirlos en el destino.

Por UDP puedes enviar tantos paquetes como quieras... si a cada paquete le añades un campo con un identificador secuencial, se pueden ordenar sin problemas al llegar al destino.

La verdad, es que dándote la razón, me gustaría hacer una prueba inicial con TCP a ver que rendimiento resulta.

Dado que TCP intenta por todos los medios garantizar la entrega de los paquetes, como la calidad de la conexión no se ajuste a la velocidad de transmisión requerida no va llegar absolutamente nada... o si llega lo va a hacer con un retraso importante.

UDP en cambio te permite gestionar la recepción de paquetes, lo que te permite descartar automáticamente paquetes antiguos sin perjudicar el rendimiento.

Los datos a transferir serían bytes. En el destino busco renderizar la imagen RGB24 usando OpenGL. Entonces lo que quiero es reconstruir el array tal cual lo envío en bytes.

La red solo entiende de tramas... y las tramas son campos de bytes... a la red le da igual si estás enviando una foto, un video porno casero o la fórmula de la cocacola... lo que tú introduzcas en un extremo de la conexión lo vas a recuperar en el otro.

Es decir, vas a enviar un chorizo de bytes y vas a recuperar un chorizo de bytes. Es responsabilidad tuya saber generar ese chorizo de bytes y, por tanto, de saber reconvertirlo en algo útil para ti.


OniRGB888* textura es un puntero a una posición de memoria. textura+1 sería el siguiente pixel y cada pixel son 3 bytes (uno por color), por lo tanto, se enviarían 3 bytes cada vez que avanzo el puntero. (Creo no equivocarme).

Como te comenté, a la red eso le da absolutamente igual. Este dato es importante para ti, lo necesitas para saber como obtener un stream de bytes que represente la imagen que quieres enviar... luego troceas ese stream en fragmentos de... no se... 1000 bytes.

Cada red tiene un tamaño máximo de trama (MTU), si la red recibe una trama mayor, la troceará para enviarla... eso es transparente para ti, pero es importante saberlo por si te genera problemas. un MTU típico es 1500, tienes que tener en cuenta que ese MTU incluye los datos que envías y la cabecera propia de cada trama, que depende del protocolo de la red.

Aquí es donde no se como tengo que enviar este objeto. Se que el método send me devuelve los bytes enviados y tengo iterar hasta envíar el frame completo. ¿Como le paso al método send la posición de memoria de este objeto?¿Como le digo que vaya en bytes en lugar de 3 bytes?

Lo primero que tienes que hacer es obtener una secuencia de bytes con la que puedas recomponer la imagen... el formato de esa secuencia puede ser libre, pero ha de ser conocido tanto por cliente como por servidor.

Después tienes que enviarlo por la red. En este caso tienes dos opciones:

* Lo envías "crudo", es decir, tal cual. El problema que te puedes encontrar es que una máquina se big endian y la otra little endian y tengas que implementar algoritmos diferentes para recomponer la imagen.

* Lo envías usando un protocolo de aplicación ya conocido ( XDR, Protocol buffers, JSon... ) estos protocolos suelen incluir codificaciones especiales para que la información se pueda recuperar sin problemas independientemente de las peculiaridades de las máquinas que intervienen en la comunicación.

Además de esto, puedes implementar tu propia capa de control. Esto te permitiría desechar mensajes antiguos y ordenar las diferentes tramas que componen una imagen. Esto se puede hacer de varias formas:

* Antes de enviar una imagen, envías un mensaje en el que indicas el número de tramas que van a componer la imagen... puedes enviar más información, como la fecha de la imagen, su número de identificación... lo que se te ocurra. Este mensaje lo recibe la máquina destino y le permite conocer de antemano lo que tiene que recibir. Luego cada parte de la imagen la tienes que enviar con el mismo identificador que la primera trama y luego un número de orden.

* Te ahorras el mensaje inicial y haces que en cada parte de la imagen viaje toda la información necesaria:

Código
  1.  
  2. #define MAX_BUFF_IMAGEN 1000
  3.  
  4. typedef struct
  5. {
  6.  int id_imagen; // Identificador de la imagen, cada imagen diferente tendra un identificador distinto
  7.  int index // Indice para poder ordenar los mensajes de una misma imagen.
  8.  int numDatos; // Numero de datos en el buffer "datos"
  9.  char[ MAX_BUFF_IMAGEN ] datos; // Buffer para almacenar un fragmento de la imagen
  10. } Trama;
  11.  
  12. void enviar( char* imagen, int longImagen )
  13. {
  14.  Trama trama;
  15.  trama.id_imagen = 0;
  16.  
  17.  int partes = longImagen / MAX_BUFF_IMAGEN;
  18.  if ( longImagen % MAX_BUFF_IMAGEN != 0 )
  19.    partes++;
  20.  
  21.  int i;
  22.  for ( i = 0; i < partes; i++ )
  23.  {
  24.    trama.index = i;
  25.  
  26.    // Se envian como mucho 1000 bytes
  27.    if ( longImagen > MAX_BUFF_IMAGEN )
  28.      trama.numDatos = MAX_BUFF_IMAGEN;
  29.    else
  30.      trama.numDatos = longImagen;
  31.  
  32.    // Se copia una parte de la imagen
  33.    memcpy( trama.datos, imagen + i * MAX_BUFF_IMAGEN, trama.numDatos );
  34.  
  35.    // Se envia el mensaje
  36.    send( socket, &trama, sizeof( trama ),  0);
  37.  }
  38. }
En línea

mk7

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Re: Sockets y concurrencia, duda básica
« Respuesta #4 en: 23 Mayo 2014, 19:25 pm »

Muchas gracias, creo que me estás convenciendo y estoy pensando en como hacerlo de esa manera.
Veo que en tu código de ejemplo envías un struct. Pero en el receptor no hay structs. Entonces había pensado hacer lo mismo pero usando un determinado numero de bytes para cada cosa. 1byte para el identificador, otro byte para el numero de trama, etc que agrego delante del frame.
¿Si envío varios frames seguidos como se cuando termina y empieza otro. Supongo que no puedo estar buscando por todos los trozos donde está una cabecera...
Si envio 2 frames seguidos y en uno el otro lado al recibir, ¿recibe el final de uno y el principio de otro?
En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Sockets y concurrencia, duda básica
« Respuesta #5 en: 23 Mayo 2014, 20:48 pm »

Tu no estás enviando un struct, como te dije, la red solo entiende de bytes, el ejemplo envía el contenido de la memoria donde se encuentra el struct.

Como te comenté, lo suyo es usar algún protocolo a nivel de aplicación que sea independiente del lenguaje de programación y de la arquitectura de la máquina. Te puse ejemplos: XDR, Protocol buffers, JSon. Estos protocolos funcionarán exactamente igual tanto en C++ como en Java, .NET, Ruby, ...

Si tu envías una trama por la red pueden pasar dos cosas: lo recibes o no lo recibes... no vas a recibir una parte sí y otra no. Si envías dos mensajes A y B en ese orden puede suceder lo siguiente:

* recibes A y B
* recibes B y A
* recibes A o B
* no recibes ninguno

No existe la opción de "recibes medio paquete de A y medio de B".

Lo de poner un secuencial en la trama es para que tu después seas capaz de ordenar los mensajes para poder recomponer la imagen correctamente.

En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
duda basica
PHP
cuerty 3 2,573 Último mensaje 17 Agosto 2008, 05:53 am
por coolfrog
Duda muy básica
PHP
HJ ~ 3 2,840 Último mensaje 28 Diciembre 2009, 01:00 am
por jdc
Tengo una duda acerca de la concurrencia en .NET trabajo
.NET (C#, VB.NET, ASP)
Matisca 0 1,606 Último mensaje 15 Enero 2015, 23:15 pm
por Matisca
Concurrencia en java
Java
josevc 2 2,439 Último mensaje 4 Enero 2016, 13:52 pm
por josevc
Cuestión de hilos/concurrencia
Java
kur79 3 2,384 Último mensaje 2 Febrero 2016, 10:18 am
por MNicolas
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines