2011-07-23 21 views
7

Estoy tratando de enviar algunos datos de un servidor C++ a un cliente C#. Pude enviar matrices de caracteres. Pero hay algún problema con la matriz flotante.Enviar matriz flotante del servidor C++ al cliente C#

Este es el código del lado del servidor C++

float* arr; 
arr = new float[12]; 
//array init... 
if((bytecount = send(*csock, (const char*)arr, 12*sizeof(float), 0))==SOCKET_ERROR){ 
} 

por lo que sí que estoy tratando de enviar a través de una red de flotadores de tamaño 12.

aquí está el código del lado del cliente. (Que era extraño que no había manera fácil de obtener el flotador fuera de la corriente en el primer lugar. Nunca he utilizado C# antes y tal vez hay algo mejor?)

//get the data in a char array 
streamReader.Read(temp, 0, temp.Length); 
//**the problem lies right here in receiving the data itself 

//now convert the char array to byte array 
for (int i = 0; i < (elems*4); i++)   //elems = size of the float array 
{ 
    byteArray = BitConverter.GetBytes(temp[i]); 
    byteMain[i] = byteArray[0]; 
} 

//finally convert it to a float array 
for (int i = 0; i < elems; i++) 
{ 
    float val = BitConverter.ToSingle(byteMain, i * 4); 
    myarray[i] = val; 
} 

veamos la memoria volcar en ambos lados y el problema quedará claro -

//c++ bytes corresponding to the first 5 floats in the array 
//(2.1 9.9 12.1 94.9 2.1 ...) 
66 66 06 40 66 66 1e 41  9a 99 41 41 cd cc bd 42 66 66 06 40 

//c# - this is what i get in the byteMain array 
66 66 06 40 66 66 1e 41  fd fd 41 41 fd 3d ? 42 66 66 06 40 

hay 2 problemas aquí en la C# secundarios 1) en primer lugar que no se ocupa de nada por encima de 0x80 (por encima de 127) (estructuras incompatibles) 2) para? ¡alguna razón increíble, cae un byte!

y esto sucede en 'temp' correcto en el momento de recibir los datos

He estado tratando de encontrar algo mejor, pero nada todavía. ¿Tiene alguna idea de por qué esto podría estar pasando? Estoy seguro de que estoy haciendo algo mal ... ¿Sugerencias para un mejor enfoque?

Muchas gracias

Respuesta

5

No está claro a partir de su código lo que los streamReader variable apunta a (es decir, ¿cuál es su tipo?), Pero yo sugeriría que utiliza el BinaryReader lugar. De esta manera, sólo puede leer datos one float at a time y no preocuparse de la matriz byte[] en absoluto:

var reader = new BinaryReader(/* put source stream here */) 
var myFloat = reader.ReadSingle(); 
// do stuff with myFloat... 
// then you can read another 
myFloat = reader.ReadSingle(); 
// etc. 

Diferentes lectores hacen cosas diferentes con los datos. Por ejemplo, el lector de texto (y el lector de flujo) asumirá que todo es texto en una codificación particular (como UTF-8) y puede interpretar los datos de una manera que no esperaba. BinaryReader no hará eso ya que fue diseñado para permitirle especificar exactamente los tipos de datos que desea leer de su transmisión.

+0

'StreamReader' se define como' System.IO.StreamReader () '. Sí, creo que 'BinaryReader' podría ser una mejor opción. Gracias déjame probarlo. – sg88

+0

gracias !! probado y probado - funciona – sg88

1

En la red, siempre debe convertir sus números a un formato común y luego volver a leerlos. En otros términos, cualquier información que no sea bytes debe ser encapsulada. Entonces, independientemente de sus lenguajes de programación, esto es lo que necesita hacer. No puedo comentar cuál es el problema con su código, pero esto podría resolver su problema y le ahorrará algo de dolor de cabeza más adelante. Piensa si la arquitectura es de 64 bits o usa endian diferente.

EDIT:
Supongo que su problema está en firmar sin firmar y se puede resolver con la respuesta de Isak, pero aún así importa lo que dije.

Si necesita ayuda con la encapsulación, consulte la Guía de red de Beej. Debería tener una muestra de cómo codificar flotadores en la red.

+0

yup lo sé. solo que si ves el volcado de memoria, algunas de las carrozas se transfieren ¡muy bien! – sg88

1

No estoy seguro acerca de C#, pero C++ no garantiza las representaciones binarias internas de los flotadores (o cualquier otro tipo de datos). Por todo lo que sabe, 0.42 podría representarse usando estos 4 bytes: '0', '.', '4', '2'.

La solución más fácil sería transferir cadenas legibles por humanos como "2.1 9.9 12.1 94.9 2.1" y usar cin/cout/printf/scanf y amigos.

+0

¿'printf' hace garantías sobre la forma de la salida? – svick

+0

Estoy de acuerdo en teoría, pero en la práctica, ¿hay realmente alguna representación de flotación diferente en uso que el IEEE 754 (que define tanto el doble como el flotar)? –

+0

(y, por cierto, C# especifica el formato de float y double para que sea como se define en el estándar mencionado anteriormente) http://msdn.microsoft.com/en-us/library/aa691146(v=vs.71).aspx –

Cuestiones relacionadas