Está en la página 1de 7

Laboratorio de Redes, Sistemas y Servicios

Práctica 1.1 Comunicación de aplicaciones mediante sockets


CURSO 2018-2019

Objetivos e introducción
En este bloque de la asignatura se va a desarrollar una serie de prácticas cuyo objetivo es la
comunicación de aplicaciones en red. En esta primera práctica se pretende que el alumno se familiarice
con el entorno de desarrollo así como con la interfaz de programación de aplicaciones que hagan uso
de la red y con la interacción de programas cliente-servidor. Más concretamente, el alumno debe
desarrollar diferentes programas que permitan emular el comando ping, pero a diferencia de este, en
esta práctica se debe realizar tanto empleando el protocolo de transporte TCP como UDP.

El objetivo principal de un socket es permitir la comunicación de procesos que pueden estar ubicados
en diferentes hosts. Así pues, un socket es una abstracción a través de la cual una aplicación puede
enviar y recibir datos de un host remoto de una manera similar a como se escribirían o leerían datos de
un fichero. Dicho de otro modo, cuando una aplicación escribe un dato en un socket, dicho dato puede
leerse por una aplicación que se encuentre en una máquina remota. Así, un socket puede verse como
un nexo entre dos aplicaciones remotas. Existen diferentes tipos de sockets dependiendo del protocolo
de transporte empleado1. De este modo, los stream sockets (SOCK_STREAM) emplean el protocolo
TCP, por lo que proveen un servicio de transporte de datos fiable. Por otro lado, los datagram sockets
(SOCK_DGRAM) usan UDP como protocolo de transporte, por lo que proveen a la aplicación de un
servicio de transporte de datagramas de usuario de tipo best effort. En esta práctica se va a hacer uso
de ambos tipos de sockets, SOCK_STREAM y SOCK_DGRAM.

Parte I - Lenguaje C
Los sockets y el modelo cliente-servidor
Como marco de referencia para la programación de sockets en lenguaje C y como punto de partida
para la programación con sockets, puede hacer uso de las Figs. 1 y 2, ambas extraídas del libro
“Programación de aplicaciones en redes de comunicaciones bajo entorno UNIX” de J.M. Arco, B.
Alarcos y A. Domingo, Servicio de Publicaciones de la UAH, 1997.

En esta práctica se va a seguir el modelo cliente-servidor, que básicamente consiste en realizar las
aplicaciones distribuidas en dos partes: el programa cliente que hace peticiones y espera la respuesta y
el programa servidor que está a la escucha permanente de peticiones las cuales, una vez las recibe,
las contesta devolviendo los resultados al cliente correspondiente.

1 Aunque existen otros tipos de sockets, en estas prácticas se consideran únicamente los sockets de Internet.
Además, dentro de los sockets de Internet existe un tipo de socket adicional a los stream y datagram sockets,
como son los raw sockets (SOCK_RAW). Aunque el estudio de los raw sockets es interesante, queda fuera del
alcance de esta práctica.
Práctica 1.1: Comunicación de aplicaciones mediante sockets

Fig. 1 Ejemplo de esquema de aplicación orientada a conexión.


Servidor

creación del socket socket ( )

asociación del socket bind ( )

crear cola de escucha listen ( )


Cliente

escucha de peticiones accept ( ) socket ( ) creación del socket

bloqueado hasta Establecimiento de la conexión


connect ( ) asociación y conexión
la conexión del cliente

datos (petición)
espera a recibir datos read ( ) write ( ) mandar datos

procesado de
Uso de la conexión
la petición

datos (respuesta)
envía datos write ( ) read ( ) espera a recibir datos

: :
peticiones y respuestas
: :
: :

Liberación de la conexión
liberar conexión close ( ) close ( ) liberar conexión

Compilación y depuración de programas en C


La manera más sencilla y rápida de compilar un programa escrito en C en Linux, el cual se encuentra
en el directorio actual y cuyo nombre de fichero es prog.c es:
cc prog.c –o prog

Cuyo resultado es, en el caso de que no existan errores, un fichero ejecutable de nombre prog.

Sin embargo, ¿qué herramientas se pueden utilizar para detectar errores en el código y en el
funcionamiento del programa? Hay fundamentalmente dos técnicas de depuración. La más
rudimentaria se basa en el empleo de mensajes por pantalla con cadenas de texto o con el valor de
ciertas variables del programa para saber cómo se está ejecutando. Esta opción, si bien es
rudimentaria, también es sencilla. Sin embargo, existen herramientas de depuración mucho más
avanzadas y ambiciosas que permiten tener al programador un control total de la ejecución de un
programa. En este caso, la herramienta que se propone es gdb, la cual está disponible en sistemas
Linux. Existen manuales de gdb (consulte la sección de referencias de este documento), aunque en
este guion se va a hacer un breve resumen del funcionamiento de gdb.

Página 2
Práctica 1.1: Comunicación de aplicaciones mediante sockets

Fig. 2 Ejemplo de esquema de aplicación no orientada a conexión.

Servidor

Cliente
creación del socket socket ( )

asociación del socket bind ( ) socket ( ) creación del socket

espera datos recvfrom ( ) bind ( ) asociación del socket


(opcional)

datos (petición)
bloqueado hasta
sendto ( ) mandar datos
recibir datos

procesado de
la petición

datos (respuesta)
envía datos sendto ( ) recvfrom ( ) espera a recibir datos

: peticiones y respuestas :
: :
: :

liberar socket close ( ) close ( ) liberar socket

En primer lugar, hay que destacar que para poder hacer uso de gdb, la compilación de un programa
debe añadir la opción –g, por lo que quedaría así:
cc prog.c –o prog -g

Una vez así compilado, para depurar el programa hay que ejecutar el comando:
gdb prog

El programa gdb posee una ayuda que se invoca mediante el comando help, la cual nos dará un listado
de los temas en los que se agrupan los diferentes comandos aceptados por gdb. Por ejemplo, para
pedir ayuda relativa a comandos de ejecución se usa help running y de ahí se puede continuar
solicitando la ayuda específica por ejemplo de la ejecución paso a paso (help next).

Nótese que los comandos en gdb se pueden repetir mediante los cursores ↑ y ↓. Los comandos de gdb
más empleados son:

➢ r: para la ejecución del programa. Nótese que se le pueden pasar parámetros de entrada al
programa del mismo modo que si se ejecutara en la shell habitual, es decir “r [parámetro_1]
[parámetros_2] …”.
➢ b num_linea: introduce un punto de parada en la línea número “num_linea”.

Página 3
Práctica 1.1: Comunicación de aplicaciones mediante sockets

➢ l num_linea: lista el número de línea “num_linea” del fichero fuente. Es útil, especialmente,
para ver dónde poner los puntos de parada.
➢ s: ejecuta la siguiente instrucción, no entrando en una función si se llama, sino ejecutándola.
La instrucción visualizada encima del cursor es la que se va a ejecutar.
➢ n: ejecuta la siguiente instrucción continuando la ejecución dentro de una función si se llama.
➢ c: continua la ejecución del programa, parando en el siguiente punto de parada o al finalizar el
programa.
➢ p nombre_variable: muestra el valor de la variable “nombre_variable” en ese instante.

Parte II - Lenguaje Python


El lenguaje Python
Python es un lenguaje de programación interpretado multiplataforma que permite la generación de
software de una manera compacta y legible. Para el alumno, el que se trate de un lenguaje interpretado
facilita su uso y experimentación con el mismo, ya que se evita el tiempo de compilación y su intérprete
puede emplearse de manera interactiva. Además, en la definición de Python se ha hecho hincapié en
su legibilidad, por lo que sus estructuras son, en general, más compactas y legibles que sus
equivalentes en C, C++ o Java, por ejemplo.

Algunas de las características del código generado en Python son:

➢ Las estructuras de datos de alto nivel permiten expresar operaciones complejas en una única
sentencia.
➢ La agrupación de sentencias se realiza mediante el uso de sangrías (indentation) en lugar del
uso de llaves (“{“, “}”), por ejemplo. Para cada nivel de sangría, se recomienda (PEP 8 - Style
Guide for Python Code) que se empleen 4 caracteres de espacio en lugar de otro número o
incluso en lugar de tabulaciones.
➢ No se requiere la declaración de variables.

Python es un lenguaje que dispone de diferentes implementaciones, siendo la más extendida y


mantenida CPython, que es la implementación de Python escrita en lenguaje C. Sin embargo, existen
otras como Jython (implementada en Java), aunque a día de hoy son minoritarias. Por ese motivo, el
alumno encontrará una gran similitud entre la programación de aplicaciones que hacen uso de la red en
C y en Python.

Además de alguno de la ingente cantidad de libros acerca del lenguaje Python, se recomienda como
bibliografía para el aprendizaje y uso del lenguaje Python su documentación oficial, que puede
encontrarse en http://www.python.org/doc/. Como podrá observar, dicha documentación está disponible
para cada versión de Python, por lo que es muy importante que consulte la documentación de la
versión que está utilizando. Por este motivo, si emplea algún libro adicional como bibliografía debe
tener en cuenta la versión de Python para la cual está escrito dicho libro, ya que Python es un lenguaje
de programación en constante evolución.

Ejecución de programas en Python


La manera más sencilla de ejecutar un programa escrito en Python, el cual se encuentra en el directorio
actual y cuyo nombre de fichero es prog.py es:
python prog.py [argumentos de entrada]

Página 4
Práctica 1.1: Comunicación de aplicaciones mediante sockets

Tenga en cuenta que pueden coexistir diferentes versiones del lenguaje Python en la misma máquina,
por lo que es importante asegurarse que se está ejecutando la versión deseada. En esta práctica se va
a emplear Python 32, el cual introdujo cambios notables respecto a Python 2.

Además, y como diferencia fundamental con el lenguaje C, es muy didáctico el uso de Python desde la
línea de comandos, sin hacer uso de un fichero con el código fuente. Para ello, únicamente debe hacer
uso del intérprete de comandos de Python mediante su ejecución.

Desarrollo de la práctica
La herramienta ping
La herramienta ping es una utilidad que permite comprobar el estado de la conexión con uno o varios
equipos remotos utilizando paquetes de solicitud de eco y de respuesta de eco. Como ejemplo, el
resultado del comando “ping –c 5 google.com” en Linux puede ser el siguiente:

PING google.com (74.125.45.100) 56(84) bytes of data.


64 bytes from yx-in-f100.google.com (74.125.45.100): icmp_seq=1 ttl=44 time=731 ms
64 bytes from yx-in-f100.google.com (74.125.45.100): icmp_seq=2 ttl=44 time=777 ms
64 bytes from yx-in-f100.google.com (74.125.45.100): icmp_seq=3 ttl=44 time=838 ms
64 bytes from yx-in-f100.google.com (74.125.45.100): icmp_seq=4 ttl=44 time=976 ms
64 bytes from yx-in-f100.google.com (74.125.45.100): icmp_seq=5 ttl=44 time=1071 ms

--- google.com ping statistics ---


5 packets transmitted, 5 received, 0% packet loss, time 4216ms
rtt min/avg/max/mdev = 731.039/879.129/1071.050/126.625 ms

Como puede observarse, el comando ping envía periódicamente paquetes de solicitud de eco los
cuales son respondidos por el equipo remoto. Puede verse como la respuesta al comando ping nos
muestra la respuesta de eco a todos los paquetes enviados, así como información adicional como el
tamaño de la solicitud y el tiempo de ida y vuelta (RTT – Round Trip Time) desde que se ha enviado
una solicitud hasta que se recibe la respuesta. Finalmente, se muestra un resumen estadístico del
resultado de la ejecución del comando.

Recuerde que se puede obtener ayuda sobre las opciones de ping tecleando ” ping /?” en Windows o
“man ping” en Linux. Además, en algunas ocasiones, el comando ping puede no obtener respuesta si el
equipo destino tiene deshabilitada la función respuesta de eco, lo que no significa que el equipo no esté
disponible.

Trabajo a desarrollar
Parte I - Lenguaje C
El objetivo de la práctica es el desarrollo de una aplicación similar a la herramienta ping empleando el
lenguaje C tanto en modo no orientado a conexión (NOC) como orientado a conexión (OC). Es decir, el
resultado de la práctica será una herramienta ping que funcione en el modo NOC y otra que funcione
en el modo OC.

El nombre de los ficheros fuente que debe emplear son los siguientes:

➢ Herramienta ping NOC:

2 En el momento de la realización de esta memoria, la última versión de Python disponible es la 3.6.4.

Página 5
Práctica 1.1: Comunicación de aplicaciones mediante sockets

✓ ping_noc.c: para el cliente ping en modo NOC.


✓ ping_noc_serv.c: para el servidor ping en modo NOC.
➢ Herramienta ping OC:
✓ ping_oc.c: para el cliente ping en modo OC.
✓ ping_oc_serv.c: para el servidor ping en modo OC.

Los parámetros de entrada para la ejecución serán los siguientes:

➢ Los clientes ping aceptan como parámetros de entrada (de manera obligatoria) el nombre de
host o dirección IP del servidor de ping junto con el puerto donde este servidor se encuentra
escuchando. Ejemplos posibles de dicha invocación serán, por tanto: “ping localhost 10000” o
“ping 127.0.0.1 10000”.
➢ Los servidores aceptan como parámetro de entrada únicamente el puerto de escucha.

Parte II - Lenguaje Python


El objetivo de la parte II de la práctica es el desarrollo de una aplicación similar a la herramienta ping
desarrollada en la parte I pero ahora empleando el lenguaje Python 3 tanto en modo no orientado a
conexión (NOC) como orientado a conexión (OC). Así, los parámetros de entrada serán los mismos
que en la parte I y los nombres de fichero también (excepto su extensión, que ahora será .py).

Herramientas útiles
Algunas de las pistas o herramientas que pueden resultar útiles para la realización de la práctica son:

➢ Se debe escoger un puerto en el servidor al cual debe conectarse el cliente. Recuerde que los
puertos 1-1023 están reservados para servicios estándar, por lo que requieren privilegios
administrativos para abrirlos. Por ese motivo, emplee números de puerto superiores a 1023.
➢ Puede ejecutar los programas cliente y servidor en la misma máquina empleando el nombre
localhost o la dirección IP 127.0.0.1. Si el cliente y servidor están en máquinas diferentes, el
comando ifconfig (Linux) o ipconfig (Windows) le puede ayudar a conocer la dirección IP de
una máquina.
➢ Los sockets deben cerrarse correctamente antes de salir del programa para que se liberen los
puertos asociados y se puedan volver a utilizar con normalidad en una ejecución próxima en el
tiempo. Recuerde que en Linux el comando “netstat –a | more” le indica el estado de los
puertos abiertos en el host local. En Windows también puede emplear el comando “netstat”.
➢ Recuerde que Wireshark puede emplearse como una herramienta muy útil que le indique qué
está ocurriendo en la red, qué mensajes se están intercambiando los hosts, qué conexiones
TCP se han abierto,…
➢ La herramienta netcat (nc en Linux) es una herramienta muy interesante para ejecutar clientes
y servidores tanto TCP como UDP, por lo que puede resultar muy útil de cara a comprobar
vuestros programas antes de tener programado tanto el cliente como el servidor. Por ejemplo,
construyendo el cliente, se puede probar con un servidor hecho con netcat. Aunque su
funcionalidad es más limitada, la herramienta telnet también permite ejecutar un cliente TCP.
➢ En C, cuando un programa requiere obtener la dirección IP de un host a partir de su
correspondiente nombre puede hacerlo mediante la función gethostbyname(). Tras ejecutar la
función anterior, en la estructura hostent el sistema operativo deja la dirección IP en el campo
h_addr, con su longitud en h_length, por lo que hay que copiar (por ejemplo con bcopy) la
dirección IP anterior, al campo sin_addr de la estructura de dirección del servidor.

Página 6
Práctica 1.1: Comunicación de aplicaciones mediante sockets

Plazo para la realización de la práctica y evaluación


Esta práctica debe realizarse por parejas por parte de los alumnos (se podrá realizar de manera
individual cuando esté debidamente justificado y autorizado por parte del profesor). Para la realización
de esta práctica dispone, además del tiempo de trabajo personal que requiera cada alumno, de tres
sesiones de dos horas cada una las semanas 1-3 de la asignatura.

La evaluación de la práctica se hará teniendo en cuenta:

➢ Presentación de memoria de la práctica donde debe constar el código fuente comentado de


los archivos desarrollados (el código debe estar como texto y no como imagen). Dicha memoria
debe enviarse con fecha límite el 20 de febrero de 2019 (inclusive) mediante el Aula Virtual
(Blackboard LS) de la asignatura. Aunque la práctica se realiza por parejas, la entrega la
realizará uno de los miembros, pero indicando el nombre de ambos.
➢ Demostración en el laboratorio de la ejecución de los programas. Al inicio de la sesión de la
semana 4 (21 de febrero de 2019) el alumno mostrará al profesor de la asignatura el
funcionamiento de las herramientas desarrolladas, pudiendo este hacer las preguntas que
estime oportunas.

Puesto que el trabajo a realizar consiste en una emulación del comando ping, el desarrollo de una
herramienta de eco únicamente permitirá alcanzar como máximo un 50% de la calificación de la
práctica.

La honestidad en el trabajo personal o de grupo debe ser una característica fundamental de un


estudiante universitario. Por este motivo, se confía en que las memorias, programas,… que se
presenten en la asignatura solo serán realizados por sus personas responsables y firmantes. La ruptura
de esta confianza implicará que los alumnos y alumnas afectados no puedan superar la asignatura.

Referencias
• José M. Arco, Bernardo Alarcos, “Programación de aplicaciones en redes de comunicaciones bajo
entorno Unix”, Servicio Publicaciones UAH, 1997.
• Michael J. Donahoo, Kenneth L. Calvert, “TCP/IP Sockets in C: Practical Guide for Programmers”,
Morgan Kauffman, 2001.
• Brian Hall, “Beej's Quick Guide to GDB”. http://beej.us/guide/bggdb/.
• W. Richard Stevens, Bill Fenner, Andrew M. Rudoff, “Unix Network Programming, Volume 1: The
Sockets Networking API”, 3ª ed., Addison-Wesley Professional, 2003.
• Documentación oficial de Python: http://www.python.org/doc/
• B. Rhodes, J. Goerzen, “Foundations of Python Network Programming: The comprehensive guide to
building network applications with Python”, 2nd Ed, Apress, 2010.

Página 7

También podría gustarte