Llamadas al sistema
getaddrinfo()
La funciรณn getaddrinfo
es una parte esencial del desarrollo de redes en C/C++. Permite a los programas resolver nombres de host y servicios, lo que significa que puede traducir un nombre de host (como www.ejemplo.com) a una direcciรณn IP y viceversa. Esto es especialmente รบtil en situaciones en las que necesitas establecer una conexiรณn de red y necesitas saber la direcciรณn IP del host o el nombre del host a partir de una direcciรณn IP.
Aun asi, su uso es bastante simple. Ayuda a configurar las estructuras que necesitarรก mรกs adelante.
Sintaxis
node
: El nombre del host o la direcciรณn IP que deseas resolver.service
: El nรบmero del puerto o el nombre del servicio al que deseas conectarte.hints
: Una estructuraaddrinfo
que proporciona pistas sobre el tipo de conexiรณn que estรกs buscando.res
: Un puntero a un puntero de estructuraaddrinfo
que se llenarรก con los resultados.
La funciรณn devuelve 0 si tiene รฉxito y un valor negativo si ocurre un error. El resultado de la funciรณn, es decir, la lista de estructuras addrinfo
, se almacena en el puntero doble res
. Es importante liberar esta memoria utilizando freeaddrinfo()
una vez que ya no se necesite la lista de direcciones.
Uso basico
Aquรญ hay una llamada de ejemplo si usted es un servidor que desea escuchar en la direcciรณn IP de su host, puerto 3490. Tenga en cuenta que esto en realidad no realiza ninguna escucha ni configuraciรณn de red; simplemente configura estructuras que usaremos mรกs adelante:
AI_PASSIVE
le dice a getaddrinfo()
que asigne la direcciรณn de mi host local a las estructuras de socket. Esto es conveniente porque asรญ no tienes que codificarla directamente. (O puedes colocar una direcciรณn especรญfica como el primer parรกmetro de getaddrinfo()
donde actualmente tengo NULL).
socket()
La funciรณn socket()
en C/C++ es una llamada al sistema que crea un nuevo socket, que es un punto de conexiรณn de red utilizado para la comunicaciรณn entre diferentes mรกquinas o procesos en la misma mรกquina.
Sintaxis
domain
: Especifica el dominio del socket. Puede serPF_INET
para IPv4,PF_INET6
para IPv6 oAF_UNIX
para comunicaciรณn local en el mismo sistema.type
: Indica el tipo de socket, comoSOCK_STREAM
para TCP (orientado a conexiรณn) oSOCK_DGRAM
para UDP (sin conexiรณn).protocol
: Generalmente se establece en0
para que el sistema seleccione el protocolo adecuado segรบn el tipo de socket y el dominio.
La funciรณn devuelve un descriptor de socket si tiene รฉxito y -1 si ocurre un error.5
Uso basico
Lo que realmente quieres hacer es usar los valores de los resultados de la llamada a getaddrinfo() e introducirlos en socket() directamente de esta manera:
socket()
simplemente le devuelve un descriptor de socket que puede usar en llamadas posteriores al sistema, o -1 en caso de error. La variable global errno
se establece en el valor del error (consulte la pรกgina de manual de errno para obtener mรกs detalles y una nota rรกpida sobre el uso de errno en programas multiproceso).
bind()
La funciรณn bind()
en C/C++ se utiliza para asociar un socket con una direcciรณn IP y un nรบmero de puerto especรญficos en el sistema local. Esto es fundamental para los servidores que esperan conexiones entrantes en un puerto especรญfico.
Sintaxis
sockfd
: El descriptor de archivo del socket que se va a asociar.addr
: Un puntero a una estructurasockaddr
que contiene la direcciรณn IP y el nรบmero de puerto.addrlen
: La longitud de la estructurasockaddr
.
La funciรณn bind()
en C/C++ devuelve 0 en caso de รฉxito y -1 en caso de error.
Uso basico
Aqui tienes un ejemplo que vincula el socket al host en el que se ejecuta el programa, el puerto 3490:
A veces, es posible que notes que intentas volver a ejecutar un servidor y bind()
falla, indicando "Address already in use" (Direcciรณn ya en uso). ยฟQuรฉ significa eso? Bueno, un pequeรฑo fragmento de socket que estaba conectado todavรญa estรก presente en el kernel y estรก ocupando el puerto. Puedes esperar a que se libere (alrededor de un minuto) o agregar cรณdigo a tu programa que le permita reutilizar el puerto, como se muestra a continuaciรณn:
Un pequeรฑo detalle adicional sobre bind()
: hay momentos en los que no serรก absolutamente necesario llamarlo. Si te estรกs conectando (connect()
) a una mรกquina remota y no te importa quรฉ puerto local estรกs utilizando (como en el caso de telnet
donde solo te importa el puerto remoto), puedes simplemente llamar a connect()
. Esta funciรณn verificarรก si el socket no estรก vinculado (bind()
) y lo vincularรก a un puerto local no utilizado si es necesario.
connect()
La funciรณn connect()
en C/C++ se utiliza para establecer una conexiรณn a un socket previamente creado y configurado. Esta funciรณn es comรบnmente usada en clientes para conectarse a servidores.
Sintaxis
sockfd
: El descriptor de socket que se quiere conectar.addr
: Un puntero a una estructurasockaddr
que contiene la direcciรณn del servidor al que se desea conectar.addrlen
: El tamaรฑo de la estructurasockaddr
.
La funciรณn connect()
devuelve un valor entero. En caso de รฉxito, devuelve 0
. Si falla, devuelve -1
y establece la variable errno
para indicar el tipo especรญfico de error que ocurriรณ durante la conexiรณn.
Uso basico
Tengamos un ejemplo en el que realizamos una conexiรณn de socket a "www.example.com", puerto 3490:
Listen()
La funciรณn listen()
en C/C++ se utiliza en servidores para esperar conexiones entrantes de clientes. Despuรฉs de crear un socket y conectarlo a una direcciรณn, el servidor llama a listen()
para comenzar a escuchar conexiones entrantes, que seran hacepatadas mediante accept()
.
Sintaxis
sockfd
: El descriptor de socket que se quiere escuchar.backlog
: El nรบmero mรกximo de conexiones pendientes que el sistema permitirรก en la cola de espera hasta que lasaccept()
es
Nuevamente, como es habitual, listen()
devuelve -1 y establece errno
en caso de error. Devuelve 0 en caso de existo
Uso basico
Bien, como probablemente puedas imaginar, necesitamos llamar a bind()
antes de llamar a listen()
para que el servidor estรฉ ejecutรกndose en un puerto especรญfico. (ยกDebes poder decirle a tus amigos a quรฉ puerto conectarse!) Asรญ que si vas a estar escuchando conexiones entrantes, la secuencia de llamadas al sistema que harรกs es:
*Dejarรฉ ese espacio como muestra de cรณdigo, ya que es bastante autoexplicativo. (El cรณdigo en la secciรณn de accept(), a continuaciรณn, es mรกs completo). La parte realmente complicada de todo este asunto es la llamada a accept()
.llll
accept()
La funciรณn accept()
en C/C++ se utiliza para aceptar una conexiรณn entrante en un socket previamente configurado. Es especialmente importante en el lado del servidor para manejar mรบltiples clientes.
Lo que va a pasar es esto: alguien muy, muy lejos intentarรก connect()
a su mรกquina en un puerto en el que estรก listen()
. Su conexiรณn estarรก en cola esperando ser accept()
. Llamas a accept()
y le dices que obtenga la conexiรณn pendiente.
ยกLe devolverรก un nuevo file descriptor de archivo de socket para usar en esta รบnica conexiรณn! Asรญ es, ยกde repente tienes dos descriptores de archivos de socket por el precio de uno! El original todavรญa estรก escuchando mรกs conexiones nuevas y el reciรฉn creado finalmente estรก listo para send()
y recv()
.
Sintaxis
sockfd
: El descriptor de socket en el que se espera una conexiรณn entrante.addr
: Un puntero a una estructurasockaddr
donde se almacenarรก la direcciรณn del cliente.addrlen
: Un puntero a un entero sin signo que indica el tamaรฑo de la estructurasockaddr
.
Nuevamente, como es habitual, listen()
devuelve -1 y establece errno
en caso de error. Devuelve 0 en caso de existo
Uso basico
Como antes, esto es un montรณn para absorber en una sola parte, asรญ que aquรญ hay un fragmento de cรณdigo de muestra para su lectura:
Nuevamente, ten en cuenta que utilizaremos el descriptor de socket new_fd
para todas las llamadas a send()
y recv()
. Si solo esperas una รบnica conexiรณn en todo momento, puedes cerrar el socket de escucha (sockfd
) para evitar mรกs conexiones entrantes en el mismo puerto, si asรญ lo deseas.
send() and recv()
Estas dos funciones son para comunicarse a travรฉs de sockets de flujo o sockets de datagramas conectados. Si deseas utilizar sockets de datagramas no conectados normales, deberรกs consultar la secciรณn sobre sendto()
y recvfrom()
.
send()
La funciรณn send()
en C/C++ se utiliza para enviar datos a travรฉs de un socket. Es comรบnmente usada en aplicaciones de red para enviar informaciรณn desde un cliente a un servidor o viceversa.
sockfd
: El descriptor de socket por el cual enviar los datos.buf
: Puntero al bรบfer que contiene los datos a enviar.len
: Tamaรฑo de los datos a enviar, en bytes.flags
: Opciones para el envรญo de datos.
send()
devuelve el nรบmero de bytes realmente enviados! Esto podrรญa ser menos que la cantidad que le indicaste que enviara. A veces le pides que envรญe un montรณn de datos y simplemente no puede manejarlo. Enviarรก tanto de los datos como pueda y confiarรก en que enviarรกs el resto mรกs tarde. Recuerda, si el valor devuelto por send() no coincide con el valor en len, depende de ti enviar el resto de la cadena.
En caso de error devuelve -1.
recv()
La funciรณn recv()
en C/C++ se utiliza para recibir datos desde un socket. Es comรบnmente usada en aplicaciones de red para recibir informaciรณn desde un cliente o servidor. Esta funciรณn se utiliza en el lado del receptor para leer los datos enviados por el lado del remitente.
sockfd
: El descriptor de socket desde el cual recibir los datos.buf
: Puntero al bรบfer donde se almacenarรกn los datos recibidos.len
: Tamaรฑo mรกximo de los datos que se pueden recibir, en bytes.flags
: Opciones para la recepciรณn de datos.
recv()
devuelve el nรบmero de bytes realmente leรญdos en el bรบfer o -1 en caso de error (con errno establecido en consecuencia).
ยกEspera! ยกrecv()
tambiรฉn puede devolver 0! Esto solo puede significar una cosa: ยกel lado remoto ha cerrado la conexiรณn contigo! Un valor de retorno de 0 es la forma en que recv() te indica que esto ha ocurrido.
Uso basico
Last updated