NOMBRE¶
recv, recvfrom, recvmsg - reciben un mensaje desde un conector
SINOPSIS¶
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int s, void *buf, size_t
lon, int flags);
ssize_t recvfrom(int s, void *buf, size_t
lon, int flags, struct sockaddr
*desde, socklen_t *londesde);
ssize_t recvmsg(int s, struct msghdr *msg, int
flags);
DESCRIPCIÓN¶
Las llamadas
recvfrom y
recvmsg se emplean para recibir mensajes
desde un conector (``socket''), y pueden utilizarse para recibir datos de un
conector sea orientado a conexión o no.
Si
desde no es NULL y el conector no es orientado a conexión, la
dirección fuente del mensaje se llena. El argumento
londesde es
un parámetro por referencia, inicializado al tamaño del
búfer asociado con
desde, y modificado cuando la función
regresa para indicar el tamaño real de la dirección guardada
ahí.
La llamada a
recv se utiliza normalmente sólo en un conector
conectado (vea
connect(2)) y es idéntica a
recvfrom con un parámetro
desde con valor NULL.
Las tres rutinas devuelven la longitud del mensaje cuando terminan bien. Si un
mensaje es demasiado largo como para caber en el búfer suministrado,
los bytes que sobran pueden descartarse dependiendo del tipo de conector del
que se reciba el mensaje (vea
socket(2)).
Si no hay mensajes disponibles en el conector, las llamadas de recepción
esperan que llegue un mensaje, a menos que el conector sea no bloqueante (vea
fcntl(2)) en cuyo caso se devuelve el valor -1 y la variable externa
errno toma el valor
EAGAIN. Las llamadas de recepción
devuelven normalmente cualquier dato disponible, hasta la cantidad pedida, en
vez de esperar la recepción de la cantidad pedida completa.
Las llamadas
select(2) o
poll(2) pueden emplearse para determinar
cuándo llegan más datos.
El argumento
flags de una llamada a recv se forma aplicando el operador
de bits
O-lógico a uno o más de los valores siguientes:
- MSG_OOB
- Esta opción pide la recepción de datos fuera-de-banda que no
se recibirían en el flujo de datos normal. Algunos protocolos ponen
datos despachados con prontitud en la cabeza de la cola de datos normales,
y así, esta opción no puede emplearse con tales
protocolos.
- MSG_PEEK
- Esta opción hace que la operación de recepción
devuelva datos del principio de la cola de recepción sin quitarlos
de allí. Así, una próxima llamada de recepción
devolverá los mismos datos.
- MSG_WAITALL
- Esta opción hace que la operación se bloquee hasta que se
satisfaga la petición completamente. Sin embargo, la llamada puede
aún devolver menos datos de los pedidos si se captura una
señal, si ocurre un error o una desconexión, o si los
próximos datos que se van a recibir son de un tipo diferente del
que se ha devuelto.
- MSG_NOSIGNAL
- Esta opción desactiva el que se produzca una señal
SIGPIPE sobre los conectores orientados a conexión cuando el
otro extremo desaparece.
- MSG_TRUNC
- Devuelve la longitud real del paquete, incluso cuando es más largo
que el búfer pasado. Esta opción sólo es
válida para conectores de paquete.
- MSG_ERRQUEUE
- Esta opción indica que los errores encolados deben recibirse desde
la cola de errores de conectores. El error se pasa en un mensaje auxiliar
con un tipo dependiente del protocolo (para IPv4 éste es
IP_RECVERR). El usuario debe proporciona un buffer de tamaño
suficiente. Vea cmsg(3) y ip(7) para obtener más
información. El contenido útil del paquete original que
provocó el error se pasa como datos normales a través de
msg_iovec. La dirección original de destino del datagrama
que provocó el error se pasa a través de
msg_name.
- Para errores locales, no se pasa ninguna dirección (ésto
puede comprobarse con el miembro cmsg_len de cmsghdr). Para
los errores recibidos, se asigna MSG_ERRQUEUE a msghdr.
Después de que se haya pasado un error, el error de conector
pendiente se regenera basándose en el siguiente error encolado y se
pasará en la siguiente operación de conectores.
El error se suministra en una estructura sock_extended_err:
#define SO_EE_ORIGIN_NONE 0
#define SO_EE_ORIGIN_LOCAL 1
#define SO_EE_ORIGIN_ICMP 2
#define SO_EE_ORIGIN_ICMP6 3
struct sock_extended_err
{
u_int32_t ee_errno; /* número de error */
u_int8_t ee_origin; /* origen del error */
u_int8_t ee_type; /* tipo */
u_int8_t ee_code; /* código */
u_int8_t ee_pad;
u_int32_t ee_info; /* información adicional */
u_int32_t ee_data; /* otros datos */
/* Pueden ir más datos a continuación .*/
};
struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);
- ee_errno contiene el número errno del error encolado.
ee_origin es el código del origen en donde se ha originado
el error. Los otros campos son específicos del protocolo. La macro
SOCK_EE_OFFENDER devuelve un puntero a la dirección del
objeto de red desde donde se ha originado el error dando un puntero al
mensaje auxiliar. Si esta dirección se desconoce, el miembro
sa_family de sockaddr contiene AF_UNSPEC y los otros
campos de sockaddr quedan indefinidos. El contenido útil del
paquete que ha producido el error se pasa como datos normales.
- Para los errores locales no se pasa ninguna dirección (esto se
puede comprobar con el miembro cmsg_len de cmsghdr). Para
los errores recibidos, se asigna MSG_ERRQUEUE a msghdr.
Después de que se haya pasado un error, el error de conector
pendiente se regenera basándose en el siguiente error encolado y se
pasará en la siguiente operación de conectores.
La llamada
recvmsg utiliza una estructura
msghdr para minimizar el
número de parámetros suministrados directamente. Esta estructura
tiene la forma siguiente, según se define en
<sys/socket.h>:
struct msghdr {
void * msg_name; /* dirección opcional */
socklen_t msg_namelen; /* tamaño de la dirección */
struct iovec * msg_iov; /* vector dispersar/agrupar */
size_t msg_iovlen; /* nº de elementos en msg_iov */
void * msg_control; /* datos auxiliares, ver más abajo */
socklen_t msg_controllen; /* long buffer datos auxiliares */
int msg_flags; /* opciones en mensaje recibido */
};
Aquí
msg_name y
msg_namelen especifican la dirección
de origen si el conector está desconectado;
msg_name puede darse
como un puntero nulo si no se desean o requieren nombres. Los campos
msg_iov y
msg_iovlen describen localizaciones dispersar/agrupar,
como se discute en
readv(2). El campo
msg_control, que tiene de
longitud
msg_controllen, apunta a un búfer para otros mensajes
relacionados con control de protocolo o para datos auxiliares diversos. Cuando
se llama a
recvmsg,
msg_controllen debe contener la longitud del
buffer disponible en
msg_control; a la vuelta de una llamada con
éxito contendrá la longitud de la secuencia de mensajes de
control.
Los mensajes son de la forma:
struct cmsghdr {
socklen_t cmsg_len; /* Nº de byte de datos, incluye cab. */
int cmsg_level; /* protocolo originante */
int cmsg_type; /* tipo específico del protocolo */
/* seguido por
u_char cmsg_data[]; */
};
Los datos auxiliares sólo deberían ser accedidos mediante las
macros definidas en
cmsg(3).
Como ejemplo, Linux usa este mecanismo de datos auxiliares para pasar errores
ampliados, opciones IP o descriptores de fichero mediante conectores Unix.
El contenido del campo
msg_flags en msghdr se establece cuando
recvmsg() regresa. Puede contener numerosas opciones:
- MSG_EOR
- indica fin-de-registro; los datos devueltos completaron un registro
(generalmente empleado con conectores del tipo
SOCK_SEQPACKET).
- MSG_TRUNC
- indica que la porción trasera de un datagrama ha sido descartada
porque el datagrama era más grande que el búfer
suministrado.
- MSG_CTRUNC
- indica que algún dato de control ha sido descartado debido a la
falta de espacio en el búfer para datos auxiliares.
- MSG_OOB
- se devuelve para indicar que se han recibido datos despachados prontamente
o fuera-de-banda.
- MSG_ERRQUEUE
- indica que no se ha recibido ningún dato sino un error ampliado de
la cola de errores de conectores.
- MSG_DONTWAIT
- Permite operaciones no-bloqueantes; si la operación se bloqueara,
se devolvería EAGAIN (también se puede conseguir
ésto usando la opción O_NONBLOCK con F_SETFL
fcntl(2)).
VALOR DEVUELTO¶
Estas llamadas devuelven el número de bytes recibidos, o bien -1 en caso
de que ocurriera un error.
ERRORES¶
Estos son algunos errores estándares generados por la capa de conectores.
Los modulos de los protocolos subyacentes pueden generar y devolver errores
adicionales. Consulte sus páginas de manual.
- EBADF
- El argumento s es un descriptor inválido.
- ECONNREFUSED
- Un host remoto no permite la conexión de red (normalmente porque no
está ejecutando el servicio solicitado).
- ENOTCONN
- El conector está asociado con un protocolo orientado a la
conexión y no ha sido conectado (vea connect(2) y
accept(2)).
- ENOTSOCK
- El argumento s no se refiere a un conector.
- EAGAIN
- El conector está marcado como no-bloqueante, y la operación
de recepción produciría un bloqueo, o se ha puesto un
límite de tiempo en la recepción, que ha expirado antes de
que se recibieran datos.
- EINTR
- La recepción ha sido interrumpida por la llegada de una
señal antes de que hubiera algún dato disponible.
- EFAULT
- El puntero a búfer de recepción (o punteros) apunta afuera
del espacio de direcciones del proceso.
- EINVAL
- Se ha pasado un argumento inválido.
4.4BSD (estas funciones aparecieron por primera vez en 4.2BSD).
NOTA¶
Los prototipos datos anteriormente siguen a glibc2. The Single Unix
Specification coincide en todo excepto en que el tipo de los valores devueltos
es `ssize_t' (mientras que BSD 4.*, libc4 y libc5 tienen `int'). El argumento
flags es un `int' en BSD 4.* pero es un `unsigned int' en libc4 y
libc5. El argumento
lon es un `int' en BSD 4.* pero es un `size_t' en
libc4 y libc5. El argumento
londesde es un `int' en BSD 4.*, libc4 y
libc5. El actual `socklen_t *' fue inventado por POSIX. Vea también
accept(2).
VÉASE TAMBIÉN¶
fcntl(2),
read(2),
select(2),
getsockopt(2),
socket(2),
cmsg(3)