2009-04-15 25 views
5

Estoy tratando de usar alguna programación de red de socket en C++. Estoy tratando de enviar el texto "¡Hola mundo!" a un servidor que usa la función C++ send(). Al principio, configuré el búfer al tamaño de 13 desde "Hello World!" en total son 12 caracteres (tienes que hacerlo uno más que el recuento de personajes). La función enviar solo envía los caracteres al servidor si lo envío alrededor de 7 veces. Y cuando finalmente llega al servidor, se ve así:C++ socket 256 byte buffer

"¡Hola, mundo! ¡Hola, mundo! ¡Hola, mundo! ¡Hola, mundo! ¡Hola, mundo! ¡Hola, mundo! ¡Hola, mundo!"

Ahora aquí está la parte divertida. El "Hola mundo!" la oración se envía inmediatamente si configuro el tamaño del búfer en 256 (búfer de caracteres [256];). Sin embargo, en lo que respecta al servidor, muestra "Hello World!" con un montón de espacio después de las dos palabras. ¿Por qué sucede esto y, si es posible, cómo puedo solucionarlo? Por favor hagamelo saber.

Gracias

+0

¿Terminaste la cadena? "¡Hola, mundo! \ 0" – Alan

Respuesta

7

Cuando se llama a read (o receive) con su búfer para leer desde el zócalo, un valor entero se devuelve que especifica el número de bytes leídos. Solo deberías tomar mucho del buffer. El resto es irrelevante:

int count = read(...); 
// buffer[0 .. count - 1] contains the appropriate data. 
+0

Y solo para que lo sepan, el servidor que recibe los datos se hace en C# – QAH

+0

QAH: Esto también es cierto para sockets C#, método Socket.Receive. –

4

tampones existen para almacenar datos hasta que esté listo para enviarlo. Tiene un tamaño de búfer de envío de 256. Hasta que se transmitan 256 caracteres a través del búfer, sus datos no se enviarán al otro lado. Puedes solucionar esto llamando a un método de descarga en tu búfer cuando sabes que estás listo para enviar.

Para que quede claro, está almacenando un buffer interno, luego el sistema operativo (o la biblioteca) vuelve a almacenar en búfer cuando llama a send() y pasa algunos datos.

Si te vuelves más específico con la biblioteca que estás utilizando y quizás incluyas un fragmento de código, probablemente podamos encontrar la función de limpieza de la memoria tampón adecuada para enviarte en tu camino.

Alternativamente, si está en * nix, simplemente apague el algoritmo de Nagle para que el sistema operativo no almacene sus pequeños paquetes. O bien, cuando configura su socket, asegúrese de utilizar la opción TCP_NODELAY

6

El algoritmo de Nagle generalmente está activado de manera predeterminada. Esto combinará varios paquetes pequeños en uno. Al desactivar el algoritmo de Nagle, se podrán enviar paquetes pequeños de inmediato.

0

Suponiendo que se trata de una toma SOCK_STREAM, lo importante es tener en cuenta que el protocolo TCP subyacente no mantiene ningún límite de segmento. Es decir, cuando llamas a send() varias veces, todos los datos que envíes pueden ser fácilmente devueltos por una única llamada a recv() en el otro extremo. O bien, los datos enviados en una llamada send() se pueden devolver en múltiples recv() s en el otro extremo, p. si algunos paquetes se retrasaron debido a la congestión de la red. Esto es fundamental para el diseño de TCP, y su aplicación debe diseñarse en consecuencia.

Además, como señala Mehrdad, la llamada a recv() devuelve la cantidad de bytes que se leyeron del cable. Cualquier cosa después de ese punto en el búfer es basura, y los datos no terminan en cero.

Un socket SOCK_DGRAM utiliza UDP por debajo, que está completamente orientado a paquetes, en oposición al flujo orientado como TCP. Sin embargo, UDP no garantiza la confiabilidad (la U significa No confiable), por lo que tiene que manejar usted mismo los paquetes perdidos, duplicados, fuera de servicio, etc. Esto es mucho más difícil que la E/S orientada a flujo.

+0

UDP es el Protocolo de datagramas de usuario; no tiene nada de poco confiable en su nombre. Estás en lo cierto de que es relativamente poco confiable, sin embargo :) –

0

La programación del zócalo es tediosa, propensa a errores y no portátil.Comience a usar bibliotecas como Boost o ACE que lo protegen de las C API de bajo nivel y le brindan abstracciones independientes de la plataforma.