2011-05-21 22 views
5

Me gustaría enviar algunos números de coma flotante de doble precisión a través de la red. (estándar C, conectores estándar) No hay htond o ntohd para convertir los datos hacia y desde el orden de bytes de la red. ¿Que debería hacer? Tengo un par de soluciones en mi cabeza, pero me gustaría saber cuál es la práctica común.host a red doble?

(También me gustaría saber cuál es la práctica común para el envío de enteros de 64 bits, al igual que los valores utilizados por gint64 gstreamer)

edición: Esta es una solución pensé. Supongo que funciona para enteros de cualquier tamaño, pero ¿es correcto para los dobles?

void swap_if_necessary (void* buff, int buff_len) 
{ 
    uint32_t foo = 1; 
    if (htonl(foo) != foo) 
    { 
     char* to_swap = (char*)buff; 

     int i; 
     for (i = 0; i < buff_len/2; i++) 
     { 
      char swap_buff = to_swap[i]; 
      to_swap[i] = to_swap[buff_len -1 -i]; 
      to_swap[buff_len -1 -i] = swap_buff; 
     } 
    } 
} 
+0

[Esta sección sobre Wikipedia] (http://en.wikipedia.org/wiki/Endianness#Floating-point_and_endianness) explica bien la situación. – hammar

+1

¿No enviarías el número entero grande de 64 bits como todos los demás números enteros? ¿Cómo sería eso diferente a otros enteros? –

+0

el problema es si debo convertirlo a big endian, o si hay alguna biblioteca que haga eso por mí. Los zócalos estándar bsd solo tienen funciones para enteros de 32 y 16 bits. –

Respuesta

5

lo que André está diciendo es que los números de punto flotante binario no son dignos de confianza a través de redes debido a las diferencias entre las distintas arquitecturas de computadora. Diferencias que van más allá del orden de bytes (big/little endian). Por lo tanto, cosas como la conversión a cadenas o el uso de bibliotecas como XDR, es realmente necesario si existe la posibilidad de que sus datos sean procesados ​​por diferentes arquitecturas de computadora.

Los formatos simples de números enteros y caracteres pueden deslizarse a través de ajustes con solo endian, pero en coma flotante se vuelve más compleja.

+1

Creo que haré mi propio intercambio de bytes, el que agregué en mi edición de preguntas, pero en las entradas de 64 bits en lugar de en dobles. Para ser honesto, las entradas de 64 bits son suficientes para mí. Deseo enviar información relacionada con el tiempo que obtengo de gstreamer. Almacena intervalos de tiempo como número de milisegundos en enteros de 64 bits. Estaba convirtiéndolos a doblar para mi propia "satisfacción" porque estoy acostumbrado a NSTimeinterval, un intervalo de tiempo almacenado como el número de segundos (punto flotante doble), que se usa en todos los marcos C de Apple (iOS y OSX) y ObjectiveC. –

4

Es posible que desee ver en XDR que fue definido por primera vez en rfc1014. Obviamente, desea encontrar una biblioteca que implemente XDR para su plataforma.

10

convertirlo a un formato de cadena de acuerdo y enviar eso. No estoy seguro si es una práctica común o incluso decente, pero funcionó para mí (es cierto que no me importaba el rendimiento en ese momento ya que no estaba enviando muchos valores).

+0

1 debido a la serialización es a menudo más fiable. –

+2

Es una práctica común en realidad. Simplemente hay demasiadas variaciones en los formatos de punto flotante. Convertir desde o hacia IEEE sería tan costoso como usar 'strtod'. Si desea enviar una gran cantidad de datos y desea conversiones baratas (sonido, posiciones en un juego en 3D en tiempo real, ...), considere enviar números de puntos fijos. –

+0

he utilizado 'sprintf (..., "%. * E", DBL_DECIMAL_DIG -1, x)' a ser suficiente para convertir de forma única 'double', (excepto NaN con una carga útil). 'sprintf (...,"% a ", x)' también es bueno. – chux

Cuestiones relacionadas