Pregunta

Estoy un poco confundido acerca de zócalo de programación en C.

Crear un socket, que se unen a una interfaz y una dirección IP y llegar a escuchar.He encontrado un par de recursos de la web en la que, y lo entendía bien.En particular, he encontrado un artículo Programación de la red de sistemas Unix ser muy informativo.

Lo que me confunde es la sincronización de los datos llegan en el zócalo.

Cómo puede usted decir que cuando los paquetes llegan, y cómo de grande el paquete, usted no tiene que hacer todo el trabajo pesado por usted mismo?

Mi suposición básica aquí es que los paquetes pueden ser de longitud variable, por lo que una vez que los datos binarios empieza a aparecer hacia abajo en el zócalo, ¿cómo se puede comenzar a construir paquetes de eso?

¿Fue útil?

Solución

Respuesta corta es que usted tiene que hacer todo el trabajo pesado a ti mismo.Usted puede ser notificado de que hay datos disponibles para ser leído, pero no se sabe cuántos bytes están disponibles.En la mayoría de los protocolos IP que utilizan paquetes de longitud variable, habrá un encabezado con un conocido de longitud fija añadida al paquete.Este encabezado contiene la longitud del paquete.Leer el encabezado, obtener la longitud de los paquetes, a continuación, lea el paquete.Repita este patrón (leer el encabezado, luego de leer el paquete) hasta que la comunicación es completa.

Al leer los datos de un socket, solicitar un número determinado de bytes.La lectura de la llamada puede bloquear hasta que el número solicitado de bytes se leen, pero puede volver menos bytes de lo que fue solicitado.Cuando esto sucede, simplemente vuelva a intentar la lea, solicitando que el resto de los bytes.

He aquí una típica función de C para la lectura de un número determinado de bytes desde un socket:

/* buffer points to memory block that is bigger than the number of bytes to be read */
/* socket is open socket that is connected to a sender */
/* bytesToRead is the number of bytes expected from the sender */
/* bytesRead is a pointer to a integer variable that will hold the number of bytes */
/*           actually received from the sender. */
/* The function returns either the number of bytes read, */
/*                             0 if the socket was closed by the sender, and */
/*                            -1 if an error occurred while reading from the socket */
int readBytes(int socket, char *buffer, int bytesToRead, int *bytesRead)
{
    *bytesRead = 0;
    while(*bytesRead < bytesToRead)
    {
        int ret = read(socket, buffer + *bytesRead, bytesToRead - *bytesRead);
        if(ret <= 0)
        {
           /* either connection was closed or an error occurred */
           return ret;
        }
        else
        {
           *bytesRead += ret;
        }
    }
    return *bytesRead;
}

Otros consejos

Por tanto, la respuesta a tu pregunta depende un poco justo si se utiliza UDP o TCP como su transporte.

En el caso de UDP, la vida se vuelve mucho más sencillo, en el que usted puede llamar a la recepción/recvfrom/recvmsg con el tamaño de paquete que usted necesita (que había probabilidades de enviar paquetes de longitud fija el origen de todos modos), y hacer la suposición de que si se dispone de datos, es allí en múltiplos de paquete de longitud tamaños.(I. E.Usted llamar a la recepción* con el tamaño de su lado de envío de paquetes, y listo.)

Para TCP, la vida se vuelve un poco más interesante - para el propósito de esta explicación, voy a suponer que usted ya sabe cómo utilizar socket(), bind(), escuchar() y accept (); esta última es la forma de conseguir que el descriptor de archivo (FD) de su recién realizado la conexión.

Hay dos formas de realizar la e/S para un socket de bloqueo, en el que la llamada read(fd, buf, N) y la lectura se sienta allí y espera hasta que he leído de N bytes a buf - o no-bloqueo, en el que tienes que comprobar (mediante select() o encuesta()) si el FD es legible y, a CONTINUACIÓN, hacer su read().

Cuando se trata con TCP basado en las conexiones, el sistema operativo no prestar atención a los tamaños de paquetes, ya que se considera un flujo continuo de datos, no separada de paquetes de tamaño de los trozos.

Si su aplicación utiliza "paquetes" (embalada o sin embalar las estructuras de datos que está pasando a su alrededor), usted debería ser capaz de llamar a read() con el tamaño adecuado argumento, y leer toda una estructura de datos en el zócalo en un momento.La única precaución que tienes que lidiar con ello, es de recordar correctamente el orden de bytes de los datos que vas a enviar, en caso de que la fuente y el destino del sistema son de diferentes byte endian-ness.Esto se aplica tanto para UDP y TCP.

Tan lejos como *NIX zócalo de programación se refiere, yo recomiendo W.Richard Stevens' "Programación De La Red Unix, Vol.1" (UNPv1) y "Programación Avanzada en un Entorno Unix" (APUE).El primero es un tomo con respecto a la red basado en la programación, independientemente de la de transporte, y el último es un buen todo-en torno libro de programación como se aplica a los basados en *NIX programación.También, busque "TCP/IP Illustrated", Volúmenes 1 y 2.

Al hacer una lectura en el zócalo, se le indica cuántos máximo de bytes a leer, pero si no tienen muchos, le da sin embargo muchos que tiene.Es hasta usted para diseñar el protocolo, de modo que ya sabes, si tienes un parcial de paquetes o no.Por ejemplo, en el pasado, cuando el envío de longitud variable binaria de datos, me gustaría poner un int en el principio de que dijo cuántos bytes a esperar.Me gustaría hacer una lectura para solicitar un número de bytes mayor que el mayor número posible de paquetes en mi protocolo, y luego me gustaría comparar la primera int en contra, sin embargo, muchos bytes que yo había recibido, y cualquiera de los procesos o intenta más lee hasta que había llegado el paquete completo, de acuerdo.

Zócalos de operar a un nivel superior que el de raw de paquetes - es como un archivo que se puede leer/escribir desde.También, cuando se intenta leer de una toma de corriente, el sistema operativo de bloque (en suspenso) el proceso hasta que haya datos para cumplir con la solicitud.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top