Transmisin UDP

Vicente González Ruiz

December 26, 2013

Contents

1 El comando ping
2 El ICMP (Internet Control Message Protocol)
3 El servidor
4 Compilacin del servidor
5 Ejecucin del servidor
6 El cliente
7 Compilacin del cliente
8 Ejecucin del cliente

El objetivo de esta prctica es implementar un Pinger utilizando el UDP (User Datagram Protocol) y as aprender a usar su API.

Un Pinger es una aplicacin de red que enva uno o varios paquetes de datos desde el host que ejecuta la parte cliente hasta el host que ejecuta la parte servidora. Esta los devuelve y permite al cliente calcular el RTT (Round-Trip Time) entre ambos hosts.

1 El comando ping

Un Pinger es una aplicacin bsica de chequeo del estado de la red. Por este motivo, en la mayora de los sistemas operativos encontramos una utilidad llamada ping. Vemos un ejemplo:

ping www.google.es  
PING www.l.google.com (72.14.221.147): 56 data bytes  
64 bytes from 72.14.221.147: icmp_seq=0 ttl=238 time=64.6 ms  
64 bytes from 72.14.221.147: icmp_seq=1 ttl=238 time=66.7 ms  
64 bytes from 72.14.221.147: icmp_seq=2 ttl=238 time=65.1 ms  
64 bytes from 72.14.221.147: icmp_seq=3 ttl=238 time=65.5 ms  
 (pulsamos <CTRL> + <c>)  
--- www.l.google.com ping statistics ---  
4 packets transmitted, 4 packets received, 0% packet loss  
round-trip min/avg/max = 64.6/65.4/66.7 ms

Como podemos ver, por defecto se envan paquetes cuyo payload contiene 56 bytes, que sumados a los 8 bytes de cabecera del IGMP dan 64 bytes, el tamao de los paquetes transmitidos (sin contar la cabecera del IP). Ntese que no se utiliza ningn protocolo de la capa de transporte.

El cliente calcula el tiempo que transcurre desde que cada paquete es enviado hasta que la correspondiente contestacin es recibida. Para finalizar, calcula el tiempo mnimo, medio y el mximo.

2 El ICMP (Internet Control Message Protocol)

La utilidad ping utiliza el protocolo de control de mensajes de Internet o ICMP. Dicho protocolo pertenece a la pila de protocolos TCP/IP y contempla un mensaje llamado Echo Request (Peticin de Eco). Cuando un host funciona adecuadamente, est conectado a Internet y no ha sido expresamente configurado para denegar las contestaciones Echo Response enva un mensaje ICMP del tipo Echo Response al host que le ha hecho la peticin.

Los mensajes de peticin y de respuesta son generalmente muy cortos. Esto significa que los tiempos de transmisin (no as los de propagacin) son prcticamente nulos y por tanto, ping se utiliza normalmente para medir el RTT entre nuestro host y el host remoto.

El Pinger presentado en esta prctica es una aplicacin que utiliza el UDP. El cliente enva paquetes UDP y el servidor los recibe y los retorna. Para describir ambas partes se ha utilizado el lenguaje de programacin Java.

3 El servidor

El servidor es bsicamente un bucle infinito que espera a recibir paquetes UDP. Para ello escucha en el puerto que se le indica por la lnea de comandos cuando es ejecutado.

Como la mayora de las ocasiones tendremos que ejecutar el cliente y el servidor en el mismo host, el servidor puede configurarse para:

  1. Simular la prdida de paquetes: Cuando el servidor y el cliente estn suficientemente alejados (en hops) los paquetes deberan perderse con una cierta probabilidad.1

    Sin embargo, dentro del mismo host o incluso en la red de laboratorio, es prcticamente imposible que se pierdan paquetes. Para simular dicho comportamiento el servidor deja de enviar un eco al cliente con una cierta probabilidad controlada por el parmetro que llamado LOSS_RATE.

  2. Simular el retraso promedio de los paquetes: El parmetro AVERAGE_DELAY se encarga de retrasar las contestaciones del servidor una determinada cantidad de tiempo, en promedio. De esta forma, se simula adems una cierta distancia entre el servidor y el cliente, aunque estos estn ejecutndose en el mismo host.

A continuacin se presenta el cdigo que implementa el servidor (http://www.ace.ual.es/\~vruiz/redes/practicas/PingServer.java):

 
1import java.io.*; 
2import java.net.*; 
3import java.util.*; 
4 
5/* 
6 * Un servidor que procesa peticiones ping sobre UDP. 
7 */ 
8public class PingServer { 
9    private static final double LOSS_RATE = 0.3; 
10    private static final int AVERAGE_DELAY = 100; // milisegundos 
11 
12    public static void main(String[] args) throws Exception { 
13        /* Comprobamos que se han introducido los parametros de entrada 
14           desde la linea de comandos. */ 
15        if (args.length < 1) { 
16            System.out.println("Youmustspecifyaport"); 
17            return; 
18        } 
19 
20        /* Puerto de escucha del servidor. */ 
21        int port = Integer.parseInt(args[0]); 
22 
23        /* Usaremos un generador de numeros aleatorios para simular la 
24         * perdida de paquetes y el retraso de la red. */ 
25        Random random = new Random(); 
26 
27        /* Creamos un socket de tipo DatragramSocket para recibir y 
28         * enviar paquetes UDP. */ 
29        DatagramSocket socket = new DatagramSocket(port); 
30 
31        /* Processing loop. */ 
32        while (true) { 
33 
34            /* Creamos la estructura de datos que nos servira para 
35               almacenar un paquete UDP. */ 
36            DatagramPacket request = new DatagramPacket(new byte[1024], 1024); 
37 
38            /* Nos bloqueamos hasta que se recibe el siguiente paquete 
39               UDP. */ 
40            socket.receive(request); 
41 
42            /* Imprimimos el payload del paquete. */ 
43            printData(request); 
44 
45            /* Decidimos si responder o simular la perdida del paquete. */ 
46            if (random.nextDouble() < LOSS_RATE) { 
47                System.out.println("Replynotsent."); 
48                continue; 
49            } 
50 
51            /* Simulamos el retraso de la red. */ 
52            Thread.sleep((int) (random.nextDouble() * 2 * AVERAGE_DELAY)); 
53 
54            /* Enviamos la respuesta. */ 
55            InetAddress clientHost = request.getAddress(); 
56            int clientPort = request.getPort(); 
57            byte[] buf = request.getData(); 
58            DatagramPacket reply = new DatagramPacket(buf, buf.length, 
59                                                      clientHost, clientPort); 
60            socket.send(reply); 
61            System.out.println("Replysent."); 
62        } 
63    } 
64 
65    /* 
66     * Imprime los datos del datagrama (payload) sobre la salida estandar. 
67     */ 
68    private static void printData(DatagramPacket request) throws Exception { 
69        /* "buf" apunta al comienzo de los datos en el paquete. */ 
70        byte[] buf = request.getData(); 
71 
72        /* Convertimos "buf" en un stream de entrada de bytes. */ 
73        ByteArrayInputStream bais = new ByteArrayInputStream(buf); 
74 
75        /* Convertimos "bais" en un stream de entrada de caracteres. */ 
76        InputStreamReader isr = new InputStreamReader(bais); 
77 
78        /* Convertimos "isr" en un stream de entrada de caracteres 
79           buffereado. Asi podremos leer lineas completas. Una linea 
80           es cualquier combinacion de caracteres que acaba en 
81           cualquier combinacion de \r y \n. */ 
82        BufferedReader br = new BufferedReader(isr); 
83 
84        /* Los datos del mensaje estan contenidos en una unica 
85           linea. Asi la leemos. */ 
86        String line = br.readLine(); 
87 
88        /* Imprimimos la direccion del host que envia el mensaje y los 
89           datos del mismo. */ 
90        System.out.println("Receivedfrom" + 
91                           request.getAddress().getHostAddress() + 
92                           ":" + 
93                           line); 
94    } 
95}

4 Compilacin del servidor

Compile el servidor usando el comando:

# Este comando genera el fichero "PingServer.class".  
javac PingServer.java

Evidntemente, deber tener instalado un compilador de Java para realizar la anterior accin. Existen versiones tanto para Linux como para Windows. Se recomienda el compilador y la mquina virtual de Sun para realizar esta parte de la prctica (http://java.sun.com) o el que se instala mediante el paquete openjdk-?-jdk.

5 Ejecucin del servidor

Ejecute el servidor con el comando:

# Recuerde que hay que utilizar un puerto mayor que 1024  
#   si no somos el usuario root. Adems, el puerto no debera estar  
#   ocupado por ningn otro proceso.  
# El fichero "PingServer.class", generado tras la compilacin,  
#  debera existir en el directorio actual.  
java PingServer 6789

6 El cliente

El cliente enva 10 peticiones de ping al servidor especificado. Cada mensaje contiene un payload de datos donde figura la cadena PING, un nmero de secuencia y una estampa de tiempo.

Tras enviar un paquete, el cliente espera hasta un segundo para recibir una respuesta. Si transcurrido este tiempo sta no llega, el cliente supone que su paquete de peticin o el paquete de respuesta (o ambos) se ha(n) perdido.

A continuacin se muestra el cdigo del cliente (http://www.ace.ual.es/\~vruiz/redes/practicas/PingClient.java):

 
1import java.io.*; 
2import java.net.*; 
3import java.util.*; 
4 
5/* 
6 * Un cliente que genera peticiones ping sobre UDP. 
7 */ 
8 
9public class PingClient { 
10    public static final String CRLF="\r\n"; 
11 
12    public static void main(String[] args) throws Exception { 
13 
14        /* Comprobamos que se han introducido los parametros de entrada 
15           desde la linea de comandos. */ 
16        if (args.length != 2) { 
17            System.out.println("Youmustspecifyaserverandaport"); 
18            return; 
19        } 
20 
21        /* Obtenemos la dir IP del servidor a partir de su nombre. */ 
22        InetAddress serverAddress = InetAddress.getByName(args[0]); 
23 
24        /* Obtenemos el puerto en el que escucha el servidor. */ 
25        int serverPort = Integer.parseInt(args[1]); 
26 
27        /* Creamos un socket de tipo DatragramSocket para enviar y 
28         * recibir paquetes UDP. */ 
29        DatagramSocket socket = new DatagramSocket(); 
30 
31        /* Asignamos un tiempo maximo de espera de recepcion a traves 
32         * de este socket (time-out) de un segundo. */ 
33        socket.setSoTimeout(1000); 
34 
35        /* Creamos la estructura de datos que almacenara un paquete UDP. */ 
36        DatagramPacket reply = new DatagramPacket(new byte[1024], 1024); 
37 
38        /* Enviamos los 10 paquetes. */ 
39        for (int i=0; i<10; ++i) { 
40 
41            /* Generamos el payload del paquete con el instante en que 
42               el paquete es generado. */ 
43            long sendingDate = (new Date()).getTime(); 
44            String payload = "Ping" + (i+1) + "" + sendingDate + CRLF; 
45            DatagramPacket request = 
46                new DatagramPacket(payload.getBytes(), 
47                                   payload.getBytes().length, 
48                                   serverAddress, 
49                                   serverPort); 
50 
51            System.out.print("Packetsentwithpayload:" + payload); 
52 
53            /* Enviamos el paquete. */ 
54            socket.send(request); 
55 
56            /* Esperamos la respuesta del servidor. */ 
57            try { 
58                socket.receive(reply); 
59            } 
60            catch(SocketTimeoutException e) { 
61                /* Se ha producido un time-out. */ 
62                System.out.println("Notresponsefromserver"); 
63                continue; 
64            } 
65 
66            /* Calculamos el tiempo que el paquete ha tardado en regresar. */ 
67            long receivingDate = (new Date()).getTime(); 
68            System.out.println("Packetreceivedafter" + 
69                               (receivingDate-sendingDate) + "miliseconds"); 
70        } 
71    } 
72}

7 Compilacin del cliente

Compile el cliente con el comando:

javac PingClient.java

8 Ejecucin del cliente

Ejecute el cliente con el comando:

java PingClient localhost 6789

Ejercicio 1: Escriba una versin del cliente y del servidor Pinger usando el lenguaje de programacin C. Compruebe que sus versiones funcionan entre s y que pueden ser intercambiadas por sus correspondientes versiones escritas en Java.

Ejercicio 2: Puede su servidor (el que usted ha escrito) atender a ms de un cliente a la vez?, es decir, podemos ejecutar ms de un cliente simultneos que usen el mismo servidor? Y el servidor que se adjunta a esta prctica, puede?

Ejercicio 3: Compruebe si el cliente y el servidor pueden correr en hosts diferentes. Qu condiciones deben darse para que la comunicacin sea posible? En otras palabras, si existe una conexin fsica entre un cliente y un servidor, y la red funciona correctamente (sin errores de transmisin), cundo no podran comunicarse entre s?