viernes, 26 de junio de 2015

el protocolo UDP



El grupo de protocolos de Internet también maneja un 
protocolo de transporte sin conexiones, el UDP (User Data Protocol, protocolo de datos de usuario). El UDP ofrece a las aplicaciones un mecanismo para enviar datagramas IP en bruto encapsulados sin tener que establecer una conexión.
Muchas aplicaciones cliente-servidor que tienen una 
solicitud y una respuesta usan el UDP en lugar de tomarse la molestia de establecer y luego liberar una conexión. El UDP se describe en el RFC 768. Un segmento UDP consiste en una cabecera de 8 bytes seguida de los datos. La cabecera se muestra a continuación. Los dos puertos sirven para lo mismo que en el TCP: para identificar los puntos terminales de las máquinas origen y destino. El campo de longitud UDP incluye la cabecera de 8 bytes y los datos. La suma de comprobación UDP incluye la misma pseudocabecera de formato, la cabecera UDP, y los datos, rellenados con una cantidad par de bytes de ser necesario.



Esta suma es opcional, y se almacena como 0 si no se calcula. Inutilizarla seria absurdo, a menos que la cantidad de los datos no importe, por ejemplo, voz digitalizada.

UDP no admite numeración de los datagramas, factor que, 
sumado a que tampoco utiliza señales de confirmación de entrega, hace que la garantía de que un paquete llegue a su destino sea mucho menor que si se usa TCP. Esto también origina que los datagramas pueden llegar duplicados y/o desordenados a su destino. Por estos motivos el control de envío de datagramas, si existe, debe ser implementado por las aplicaciones que usan UDP como medio de transporte de datos, al igual que el reeensamble de los mensajes entrantes.
Es por ello un protocolo del tipo best-effort (máximo 
esfuerzo), porque hace lo que puede para transmitir los datagramas hacia la aplicación, pero no puede garantizar que la aplicación los reciba.


Tampoco utiliza mecanismos de detección de errores. 
Cuando se detecta un error en un datagrama, en lugar de 
entregarlo a la aplicación destino, se descarta.
Cuando una aplicación envía datos a través de UDP, éstos 
llegan al otro extremo como una unidad. Por ejemplo, si una aplicación escribe 5 veces en el puerto UDP, la aplicación al otro extremo hará 5 lecturas del puerto UDP. Además, el tamaño de cada escritura será igual que el tamaño de las lecturas.

Aplicación del Protocolo



   Los usos principales de este protocolo son el Servidor de Nombres de
   Internet  y la Transferencia Trivial de Ficheros (Trivial File
   Transfer)


Número del protocolo

   Este es el protocolo 17 (21 en octal) cuando se utilice en el
   Protocolo de Internet (IP). Se indican otros números de protocolo en
   


Referencias


  Postel,   J.,   "Internet  Protocol,"  RFC 760,  USC/Information
     Sciences Institute, Enero de 1980.  (Nota del T. Hay traducción al
     español por P.J. Ponce de León: "Protocolo Internet", Mayo 1999.)

  Postel,   J.,   "Transmission   Control   Protocol,"   RFC 761,
     USC/Information Sciences Institute, Enero de 1980.




J. Postel                                                     

RFC 768          Protocolo de Datagramas de Usuario       28 Agosto 1980


  Postel,   J.,  "Internet  Name Server,"  USC/Information Sciences
     Institute, IEN 116, Agosto de 1979.

  Sollins,  K.,  "The TFTP Protocol,"  Massachusetts  Institute of
     Technology, IEN 133, Enero de 1980.

  Postel,   J.,   "Assigned   Numbers,"  USC/Information  Sciences
     Institute, RFC 762, Enero de 1980.


Nota del traductor

     Este documento y las traducciones al español mencionadas en las
     referencias pueden encontrarse en:
     http://lucas.hispalinux.es/htmls/estandares.html

     El proyecto de traducción de RFC al español tiene su
     web de desarrollo en:

     http://www.arrakis.es/~pjleon/rfc-es

Campos



   El campo Puerto de Origen es opcional; cuando tiene 
sentido, indica
   el puerto del proceso emisor, y puede que se asuma que 
ése sea el
   puerto al cual la respuesta debería ser dirigida en 
ausencia de otra
   información. Si no se utiliza, se inserta un valor cero.

   El campo Puerto de Destino tiene significado dentro del 
contexto de
   una dirección de destino en un entorno internet particular.

   El campo Longitud representa la longitud en octetos de 
este datagrama
   de usuario, incluyendo la cabecera y los datos. (Esto 
implica que el
   valor mínimo del campo Longitud es ocho.)

   El campo Suma de Control (Checksum) es el complemento a uno de 16
   bits de la suma de los complementos a uno de las palabras de la
   combinación de una pseudo-cabecera construída con información de la
   cabecera IP, la cabecera UDP y los datos, y rellenada con octetos de
   valor cero en la parte final (si es necesario) hasta tener un
   múltiplo de dos octetos.

   La pseudo-cabecera que imaginariamente antecede a la cabecera UDP
   contiene la dirección de origen, la dirección de destino, el
   protocolo y la longitud UDP. Esta información proporciona protección
   frente a datagramas mal encaminados. Este procedimiento de
   comprobación es el mismo que el utilizado en TCP.



                     0      7 8     15 16    23 24    31
                    +--------+--------+--------+--------+
                    |        dirección de origen        |
                    +--------+--------+--------+--------+
                    |        dirección de destino       |
                    +--------+--------+--------+--------+
                    |  cero  |protocol|  longitud UDP   |
                    +--------+--------+--------+--------+


   Si la suma de control calculada es cero, se transmite como un campo
   de unos (el equivalente en la aritmética del complemento a uno). Un
   valor de la suma de control trasmitido como un campo de ceros
   significa que el el emisor no generó la suma de control (para
   depuración o para protocolos de más alto nivel a los que este campo
   les sea indiferente).


Interfaz de Usuario

   Un interfaz de usuario debería permitir:




J. Postel                                                       [Pág. 2]

RFC 768          Protocolo de Datagramas de Usuario       28 Agosto 1980


      la creación de nuevos puertos de recepción,

      operaciones de recepción en los puertos de recepción que devuelvan
      los octetos de datos y una indicación del puerto de origen y de la
      dirección de origen,

      y una operación que permita enviar un datagrama, especificando los
      datos y los puertos de origen y de destino y las direcciones a las
      que se debe enviar.



Interfaz IP

   El módulo UDP debe ser capaz de determinar las direcciones de origen
   y destino en un entorno internet así como el campo de protocolo de la
   cabecera del protocolo internet. Una posible interfaz UDP/IP
   devolvería el datagrama de internet completo, incluyendo toda la
   cabecera, en respuesta a una operación de recepción. Un interfaz de
   este tipo permitiría también al módulo UDP pasar un datagrama de
   internet completo con cabecera al módulo IP para ser enviado. IP
   verificaría ciertos campos por consistencia y calcularía la suma de
   control de la cabecera del protocolo internet.



Comparativa entre UDP y TCP (Transmission Control Protocol)

  • UDP: proporciona un nivel de transporte no fiable de datagramas, ya que apenas añade la información necesaria para la comunicación extremo a extremo al paquete que envía al nivel inferior. Lo utilizan aplicaciones como NFS (Network File System) y RCP (comando para copiar ficheros entre ordenadores remotos), pero sobre todo se emplea en tareas de control y en la transmisión de audio y vídeo a través de una red. No introduce retardos para establecer una conexión, no mantiene estado de conexión alguno y no realiza seguimiento de estos parámetros. Así, un servidor dedicado a una aplicación particular puede soportar más clientes activos cuando la aplicación corre sobre UDP en lugar de sobre TCP.
  • TCP: es el protocolo que proporciona un transporte fiable de flujo de bits entre aplicaciones. Está pensado para poder enviar grandes cantidades de información de forma fiable, liberando al programador de la dificultad de gestionar la fiabilidad de la conexión (retransmisiones, pérdida de paquetes, orden en el que llegan los paquetes, duplicados de paquetes...) que gestiona el propio protocolo. Pero la complejidad de la gestión de la fiabilidad tiene un coste en eficiencia, ya que para llevar a cabo las gestiones anteriores se tiene que añadir bastante información a los paquetes que enviar. Debido a que los paquetes para enviar tienen un tamaño máximo, cuanta más información añada el protocolo para su gestión, menos información que proviene de la aplicación podrá contener ese paquete (el segmento TCP tiene una sobrecarga de 20 bytes en cada segmento, mientras que UDP solo añade 8 bytes). Por eso, cuando es más importante la velocidad que la fiabilidad, se utiliza UDP. En cambio, TCP asegura la recepción en destino de la información para transmitir.



Transmisión de vídeo y voz

UDP es generalmente el protocolo usado en la transmisión 
de vídeo y voz a través de una red. Esto es porque no hay tiempo para enviar de nuevo paquetes perdidos cuando se está escuchando a alguien o viendo un vídeo en tiempo real.
Ya que tanto TCP como UDP circulan por la misma red, en muchos casos ocurre que el aumento del tráfico UDP daña 
el correcto funcionamiento de las aplicaciones TCP. Por defecto, TCP pasa a un segundo lugar para dejar a los datos en tiempo real usar la mayor parte del ancho de banda. El problema es que ambos son importantes para la mayor parte de las aplicaciones, por lo que encontrar el equilibrio entre ambos es crucial.

Todo este tipo de protocolos son usados en telemática.

cómo usar el protocolo UDP para una comunicación cliente/servidor


Servidor:
import socketserver
print("Servidor iniciado...")
class MyUDPHandler(socketserver.BaseRequestHandler):
    def handle(self):
       
data = self.request[0].strip()
        socket = self.request[1]
       
print("{0} Ha escrito:".format(self.client_address[0]))
        print(data)
        socket.sendto(data.upper(), self.client_address)
if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
    server = socketserver.UDPServer((HOST, PORT), MyUDPHandler)
    server.serve_forever()
Cliente (Cambia "localhost" por la dirección IP del servidor.):
import socket
import sys
print("Cliente iniciado...")
HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.sendto(bytes(data + "\n","utf8"), (HOST, PORT))
received = sock.recv(1024)

print("Enviado: {0}".format(data))
print("Recibido: {0}".format(received))
Código de ejemplo (C)[editar]
El siguiente ejemplo muestra cómo usar el protocolo UDP para una comunicación cliente/servidor:

Servidor:
#include <winsock.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")

const int BufLen = 1024;

int main()
{
         WSADATA wsaData;
        
SOCKET RecvSocket;
         sockaddr_in RecvAddr;
         int Puerto = 2345;
         char RecvBuf[BufLen];
         sockaddr_in SenderAddr;
         int SenderAddrSize = sizeof(SenderAddr);
         WSAStartup(MAKEWORD(2,2), &wsaData);
         RecvSocket = socket(AF_INET, SOCK_DGRAM, 

IPPROTO_UDP);
         RecvAddr.sin_family = AF_INET;
         RecvAddr.sin_port = htons(Puerto);
         RecvAddr.sin_addr.s_addr = INADDR_ANY;
         bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr));
         recvfrom(RecvSocket,RecvBuf, BufLen,0,(SOCKADDR *)&SenderAddr,&SenderAddrSize);
         printf("%s\n",RecvBuf);
         closesocket(RecvSocket);
         WSACleanup();
}
Cliente (Cambia "127.0.0.1" por la dirección IP del servidor):
#include <winsock.h>
#pragma comment(lib,"ws2_32.lib")

int main()
{
         WSADATA wsaData;
         SOCKET SendSocket;
         sockaddr_in RecvAddr;
         int Puerto = 2345;
         char ip[] = "127.0.0.1";
         char SendBuf[] = "Hola!!!!";
         WSAStartup(MAKEWORD(2,2), &wsaData);
         SendSocket = socket(AF_INET, SOCK_DGRAM, 

IPPROTO_UDP);
         RecvAddr.sin_family = AF_INET;
         RecvAddr.sin_port = htons(Puerto);
         RecvAddr.sin_addr.s_addr = inet_addr(ip);
         sendto(SendSocket,SendBuf,strlen(SendBuf)+1,0,(SOCKADDR *) &RecvAddr,sizeof(RecvAddr));
         WSACleanup();

}

ejemplo como usar el protocolo UDP



Servidor:
public static void main(String[] args) {

                   try {
                            System.out.println("server creado........");
                            // 1. crear el servidor..
                           
DatagramSocket socket = new DatagramSocket(45000);

                            // 2. recibir mensaje desde el cliente...

                            // 2.1 crear el paquete donde se recibe el mensaje.
                            byte[] buffer = new byte[1024];
                           

DatagramPacket paqueteCliente = new 
DatagramPacket(buffer, 1024);
                            // 2.2 recibir el paquete. operacion bloqueante.
                            System.out.println("socket esperando....");
                            socket.receive(paqueteCliente);

                            // 2.3 leer el paquete como string...
                            String msj = new String(paqueteCliente.getData());

                            System.out.println("desde "
                                               + paqueteCliente.getAddress().getHostAddress()
                                               + " desde el puerto " + paqueteCliente.getPort()
                                               + " se recibio:" + msj);

                            // 3. enviar respuesta..
                            String resp = new Date().toString();// la hora como respuesta.
                            // 3.1 crear datagrama de envio.
                            // direccion destino..
                            InetAddress addr = paqueteCliente.getAddress();// la misma del
                                                                                                                 // cliente.
                            int port = paqueteCliente.getPort();
                            // el datagrama contiene la información del destino.
                            DatagramPacket paqueteEnvio = new DatagramPacket(resp.getBytes(),
                                               resp.length(), addr, port);
                            System.out.println("enviando:"+new String(paqueteEnvio.getData()));
                            // 3.2 enviar paquete...
                            socket.send(paqueteEnvio);

                            //4. cerrar el socket...
                            socket.close();

                   } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                   }

         }
Cliente:
public static void main(String[] args) {
                   try {

                            // 1. crear el socket por donde se enviara la peticion y se recibira
                            // la respuesta..
                            DatagramSocket socket = new DatagramSocket(32000);

                            // 2. crear datagrama para enviar la info. el datagrama contiene
                            // toda la info necesaria para que llegue el msj
                            String msj = "Hola Server....."; // msj a enviar.
                            String ip = "127.0.0.1";
                            int port = 45000;
                            // 2.1 crear datagrama
                            DatagramPacket paqueteEnvio = new DatagramPacket(msj.getBytes(),
                                               msj.length(), InetAddress.getByName(ip), port);
                            // 2.2 enviar paquete.
                            socket.send(paqueteEnvio);

                            // 3. recibir respuesta...

                            // 3.1 crear datagrama de recepcion.
                            byte[] resp = new byte[1024];
                            DatagramPacket paqueteRecibido = new DatagramPacket(resp,
                                               resp.length);

                            // 3.2 recibir paquete.
                            socket.receive(paqueteRecibido);

                            // 4. mostrar info...
                            System.out.println("Server respondio desde "
                                               + paqueteRecibido.getAddress().getHostAddress()
                                               + " por el puerto " + paqueteRecibido.getPort()
                                               + " se recibio:" + new String(paqueteRecibido.getData()));

                            // 5. cerrar
                            socket.close();

                   } catch (IOException e) {
                            e.printStackTrace();
                   }


         }




Características del protocolo UDP



El protocolo UDP (Protocolo de datagrama de usuario) es un protocolo no orientado a conexión de lacapa de transporte del modelo TCP/IP. Este protocolo es muy simple ya que no proporciona detección de errores (no es un protocolo orientado a conexión).

Por lo tanto, el encabezado del segmento UDP es muy simple:

Significado de los diferentes campos

  • Puerto de origen: es el número de puerto relacionado con la aplicación del remitente del segmento UDP. Este campo representa una dirección de respuesta para el destinatario. Por lo tanto, este campo es opcional. Esto significa que si el puerto de origen no está especificado, los 16 bits de este campo se pondrán en cero. En este caso, el destinatario no podrá responder (lo cual no es estrictamente necesario, en particular para mensajes unidireccionales).
  • Puerto de destino: este campo contiene el puerto correspondiente a la aplicación del equipo receptor al que se envía.
  • Longitud: este campo especifica la longitud total del segmento, con el encabezado incluido. Sin embargo, el encabezado tiene una longitud de 4 x 16 bits (que es 8 x 8 bits), por lo tanto la longitud del campo es necesariamente superior o igual a 8 bytes.
  • Suma de comprobación: es una suma de comprobación realizada de manera tal que permita controlar la integridad del segmento.

puerto de origen
(16 bits);
puerto de destino
(16 bits);
longitud total
(16 bits);
suma de comprobación del encabezado
(16 bits);
Datos
(longitud variable).

User Datagram Protocol

User Datagram Protocol (UDP) es un protocolo del nivel de transporte basado en el intercambio de datagramas (Encapsulado de capa 4 Modelo OSI). Permite el envío de datagramas a través de la red sin que se haya establecido previamente una conexión, ya que el propio datagrama incorpora suficiente información de direccionamiento en su cabecera. Tampoco tiene confirmación ni control de flujo, por lo que los paquetes pueden adelantarse unos a otros; y tampoco se sabe si ha llegado correctamente, ya que no hay confirmación de entrega o recepción. Su uso principal es para protocolos como DHCPBOOTPDNS y demás protocolos en los que el intercambio de paquetes de la conexión/desconexión son 
mayores, o no son rentables con respecto a la información transmitida, así como para la transmisión de audio y vídeo en real, donde no es posible realizar retransmisiones por los estrictos requisitos de retardo que se tiene en estos casos.