Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner el enlace http://www.chuidiang.org

Librería sencilla de Sockets para C y Linux

Para los ejemplos de esta página de sockets, he hecho una pequeña librería. Es necesaria para todos los ejemplos de sockets, excepto el primero de todos. Esta librería también te puede ser útil para empezar a programar con sockets, aunque posiblemente la acabes modificando y ampliando o haciéndote una propia.

La librería tiene las siguientes funciones:

SERVIDOR

int Abre_Socket_Unix (char *) Abre un socket AF_UNIX. Este tipo de socket no sale por red, así que sólo permite comunicar programas dentro del mismo ordenador. Se le pasa un nombre de fichero que o bien no existe, o bien ya ha sido creado por él. Este nombre debe saberlo y utilizarlo el cliente. Devuelve el descriptor del socket servidor, que debemos guardarnos. -1 en caso de error.
int Abre_Socket_Inet (char *) Abre un socket AF_INET. Este tipo de socket sí sale por red y permite comunicar programas que se ejecuten en distintos ordenadores. Se le pasa un nombre de servicio tcp que esté dado de alta en el fichero /etc/services. Devuelve el descriptor del socket servidor y debemos guardárnoslo. -1 en caso de error.
int Acepta_Conexion_Cliente (int) Se queda bloqueada hasta que un cliente se conecte. Se le pasa el descriptor de socket servidor obtenido con cualquiera de las funciones anteriores. Devuelve el descriptor del socket cliente, con el que podremos leer o escribir datos al cliente. -1 en caso de error.
int Abre_Socket_Udp (char *) Abre un socket UDP para atender el servicio cuyo nombre se le pasa como parámetro. El servicio debe estar dado de alta en /etc/servicies como udp. La función devuelve el descriptor del socket si todo ha ido bien o -1 en caso de error.

CLIENTE

int Abre_Conexion_Unix (char *) Establede una conexión AF_UNIX con el servidor. Se le pasa el mismo fichero que se pasó en el servidor a la función Abre_Socket_Unix(), con el mismo path. Devuelve el descriptor de fichero que nos permite enviar o recibir datos del servidor. -1 en caso de error.
int Abre_Conexion_Inet (char *) Establece una conexión AF_INET con el servidor. Se le pasa el mismo nombre de servicio que se le pasó al servidor en la función Abre_Socket_Inet() y que está dado de alta en el fichero /etc/services. Devuelve el descriptor de fichero que nos permite enviar o recibir datos del servidor. -1 en caso de error.
int Abre_Conexion_Udp () Abre un socket UDP para un cliente. El sistema operativo elige un servicio/puerto que esté libre. La función nos devuelve el descriptor del socket o -1 si ha habido algún error.

COMUNES

int Lee_Socket (int, char *, int) Sirve para leer datos de un socket abierto, Se le pasa:
  • el descriptor obtenido con la función Abre_Conexion_Unix(), Acepta_Conexion_Inet()  o Acepta_Conexion_Cliente()
  • un buffer en el que queramos recibir (puede ser un puntero a cualquier estructura de datos que ya esté creada haciendo el cast adecuado) 
  • el número de bytes que queremos leer del socket (y que deben caber en el buffer que pasemos).
A la vuelta  el buffer queda relleno con los datos leidos del socket. Devuelve el número de bytes leido si no ha habido problemas, 0 si en el otro extremo han cerrado el socket y -1 en caso de error.
int Escribe_Socket (int, char *, int) Como la anterior, pero para escribir datos. El buffer debe contener los datos que queremos enviar.
int Lee_Socket_Udp (int, struct sockaddr *,
int *, char *, int)
Lee un mensaje de un socket UDP, obtenido con Abre_Conexion_Udp() o Abre_Socket_Udp(). La función se queda bloqueada hasta que llegue el mensaje o se produzca algún error. Se le pasa:
  • El descriptor del socket del que debe leer.
  • Una estructura sockaddr. Cuando se lea el mensaje, en esta estructura la función nos devolverá los datos del que nos ha enviado el mensaje. Debemos guardarlos si queremos responderle.
  • Un puntero a entero. El entero debe contenter el tamaño de la estructura anterior.
  • El buffer donde la función dejará el mensaje. Puede ser un puntero a cualquier estructura de datos que queramos, haciendo el cast a char *.
  • La longitud del mensaje que queremos leer.
La función devuelve el número de bytes leidos o -1 en caso de error.
int Escribe_Socket_Udp (int, 
struct sockaddr *,int, char *, int)
Envía un mensaje por un socket UDP, obtenido con Abre_Conexion_Udp() o Abre_Socket_Udp(). Se le pasa:
  • El descriptor del socket por el que va a enviar el mensaje.
  • Una estructura sockaddr con el destinatario del mensaje. Esta estructura la obtenemos con la función anterior al recibir un mensaje, o bien con la función Dame_Direccion_Udp().
  • Un entero con el tamaño de la estructura anterior.
  • El buffer con el mensaje que queremos enviar. Puede ser un puntero a cualquier estructura de datos que queramos, haciendo el cast a char *
  • Un entero con el tamaño del mensaje que queremos enviar (que está contenido en el buffer anterior).
La función devuelve el número de bytes escritos en el socket o -1 en caso de error.
int Dame_Direccion_Udp (char *, char *, struct sockaddr *, int *) Esta función es útil para rellenar estructuras sockaddr de una forma sencila.
Se le pasa:
  • el nombre de un host (dado de alta en /etc/hosts). Puede ser NULL si la estructura se usa para un bind() de un servidor udp.
  • el nombre de un servicio (dado de alta en /etc/services como udp). Puede ser NULL si queremos que el sistema operativo elija un servicio/puerto que esté libre (útil para bind() de clientes udp)
  • un puntero a una estructura sockaddr, que nos devolverá rellena con el host y servicio indicado.
  • un puntero a entero, en el que pasamos el tamaño de la estructura. Este parámetro se ignora.
La función devuelve -1 en caso de error. Ojo. He visto un error falta un return 0 al final, con lo que puede fallar aunque lo haga bien.

Para cerrar los sockets basta con llamar a la función close() pasándole el descriptor del socket. No he hecho una función para eso.

Para obtener la librería, necesitas los ficheros Socket.c, Socket.h, Socket_Servidor.c, Socket_Servidor.h, Socket_Cliente.c, Socket_Cliente.h y Makefile. Descárgalos, quítales la extensión .txt y compilalos con make. Se creará un librería libChSocket.a. Acuérdate del directorio donde dejas todo esto, que en los ejemplos te hará falta indicar el path de esta librería y de sus .h. También puedes descargarlo todo junto con ChSocket.tar.gz

Para utilizarla con tus propios programas, si <path> es el directorio donde has puesto todo esto, la orden de compilación sería parecida a esto

cc miprograma.c -I<path> -L<path> -lChSocket -o miprograma

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007: