19 ago 2012

cliente-servidor UDP en Linux

El primer ejemplo que mostraré es la creación de un cliente servidor NO orientado a conexión (UDP).
Para esto haremos uso del lenguaje C y del manejo de sockets.

Creación del Cliente :
Un cliente NO orientado a conexión sigue la siguiente estructura:

Creación del servidor:
El servidor NO orientado a conexión sigue la siguiente estructura:

 Para crear un cliente-servidor debemos de saber que es un socket, así que antes de empezar a programar daremos un pequeño resumen de las funciones mencionadas anteriormente.

¿Qué es un socket?
De manera sencilla diremos que un socket es un conector electrónico por el cual dos programas pueden intercambiar datos de forma correcta.

Para lograr la comunicación del cliente con el servidor debemos crear el socket, para esto haremos uso de la función socket(), esta función retorna un descriptor de socket que es de tipo int.

sockfd = socket(int dominio, int tipo, int protocolo):

    sockfd: es el descriptor del socket devuelto, lo utilizaremos para recibir y enviar datos.
    dominio: dominio donde se realiza la conexión, para este ejemplo usaremos AF_INET
    tipo: Especifica la semántica de la comunicación, sus valores mas comunes son SOCK_STREAM  si es orientado a conexión (TCP) y SOCK_DGRAM si NO es orientado a conexión (UDP).
    protocolo: Protocolo particular para ser usado con el conector, generalmente usaremos el valor de 0.

Si tiene éxito, la función devuelve un int que indica el valor del conector. En caso de error el valor es -1.

para hacer uso de la función socket() debemos incluir las bibliotecas :
#include <sys/types.h>
#include <sys/socket.h>


La función bind()  asocia el socket dado por sockfd a la dirección especificada por addr.
 bind(int sockfd, struct sockaddr* addr, int addrlen)

sockfd: Descriptor del socket creado con anterioridad.
addr: Estructura de datos en la que se define la dirección y el puerto al que se asocia el socket.
addrlen: Longitud de la estructura de datos anterior.

La estructura sockaddr no suele ser utilizada, es mas común encontrarse con sockaddr_in, cuya descripción se muestra a continuación:

struct in_addr{
  unsigned long int s_addr;
}

struct sockaddr_in{
  int sin_family;
  unsigned short int sin_port;
  struct in_addr sin_addr;

sin_family: Dominio de comunicaciones del socket (generalmente AF_INET).
sin_port: Puerto al que se asocia el socket.
sin_addr.s_addr: Dirección IP a la que se asocia el socket. 

En caso de error la funcion bind() retorna -1, para hacer uso de esta función debemos incluir las siguientes bibliotecas:

#include <sys/types.h>
#include <sys/socket.h>

La función
sendto(int sockfd, const void *buf, int lonbuf, int flags, const struct sockaddr*addr, int lonaddr); 

Esta función escribe "buflen" bytes de datos mediante el socket especificado por sockfd.

sockfd: Descriptor del socket creado con anterioridad.
buf: Puntero a buffer, buf contiene los datos a escribir en el socket.
lonbuf:  Longitud de los datos a enviar.
flags: Opciones de envío, por lo general se usa el valor de 0.
addr: Estructura que contiene la dirección y el puerto por el cual se va a enviar la información.
lonaddr: Longitud de la estructura de datos anterior.

En caso de error la función sendto() retorna -1, para poder usar esta función debemos incluir las siguientes bibliotecas.

#include <sys/types.h>
#include <sys/socket.h>

 La función

recvfrom(int sockfd, const void *buf, int lonbuf,int flags, const struct sockaddr *from, int lonfrom );

Esta función almacena los datos recibidos en buf, estos datos provienen de la dirección ip contenida en la estructura from.

sockfd: Descriptor del socket creado con anterioridad.
buf: Puntero a buffer, buf contiene los datos recibidos.
lonbuf: Longitud de los datos recibidos.
flags: Opciones de recepción, generalmente 0.
from: Estructura de datos que contiene la dirección IP y el puerto por el cual se han enviado los datos a recibir.
lonfrom: Longitud de la estructura de datos anterior.

Para poder usar esta función debemos incluir las bibliotecas:

#include <sys/types.h>
#include <sys/socket.h>

la función close(int sockfd);
es la mas sencilla de entender, recibe como argumento el descriptor del socket que queremos cerrar. Esta función retorna 0 en caso de cerrar correctamente el socket, de no ser así retorna -1.
Para usar la función close()  debemos incluir la biblioteca

#include <unistd.h>


. . . y así doy por finalizado este pequeño tutorial, pero pronto publicaré el código fuente que implementa tanto al cliente como al servidor.




2 comentarios:

  1. MUY BUENO. PREGUNTA EN TCP HACIA ESO PERO DSPS DEL BIND ASI ESTO PARA RECIBIR CONEXIONES? EN UDP NO HACE FALTA ESTO

    int listen(int sockfd, int backlog);

    ResponderEliminar
  2. No, debido a que UDP es NO orientado a Conexión, por lo que los mensajes pueden ser enviados de un punto final a otro sin previo aviso, en otras palabras, el emisor transmite datos sin tener que asegurarse de que el receptor este disponible y listo para recibir esos datos.

    ResponderEliminar