Sei sulla pagina 1di 12

UNIVERSIDAD NACIONAL DE SAN AGUSTÍN

ESCUELA PROFESIONAL DE INGENIERÍA ELECTRÓNICA


TELEMÁTICA II

Diseño y Desarrollo de una Aplicación UDP para la


Solicitud de Fecha de un Servidor Unix

Proyecto Final del Curso

DOCENTE:
Ing. Ramiro Gustavo Banda Valdivia

INTEGRANTES:
Ccahuachia Ramos Leonidas Ruben
Kana Chuctaya Alex Ronald
Luque Coila Miguel
Cruz Trujillo Ivan Alex
Vivas Apaza Jesús Ángel

2018

1
Índice
1. INTRODUCCIÓN 3

2. OBJETIVO GENERAL 3

3. OBJETIVOS ESPECÍFICOS 3

4. MATERIALES Y EQUIPO 3

5. MARCO TEÓRICO 4
5.1. TIEMPO UNIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
5.2. BREVE RESUMEN DE UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
5.3. EL ARDUINO NANO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
5.4. MODULO HanRun HR911105A . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

6. DESARROLLO Y RESULTADOS 6
6.1. DESARROLLO DEL CÓDIGO . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
6.2. EXPLICACIÓN DE LAS PARTES MAS IMPORTANTES DEL CÓDIGO . . . 8
6.3. EJECUCIÓN Y RESULTADOS . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

7. CONCLUSIONES 11

8. REFERENCIAS 11

Índice de figuras
1. El formato de un datagrama de usuario UDP . . . . . . . . . . . . . . . . . . . . 4
2. Ilustración del pseudo encabezado utilizado para calcular el UDP . . . . . . . . 5
3. Arduino Nano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
4. Descripción del Arduino Nano . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
5. Modulo HanRun HR911105A . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
6. Prueba sin conexión a Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2
Diseño y Desarrollo de una Aplicación UDP para la
Solicitud de Fecha de un Servidor Unix

1. INTRODUCCIÓN
La Telemática es uno de los más importantes desarrollos en el campo de la educación, ya que
la información es la materia prima que necesitamos para crear conocimientos con los que se
afrontan las problemáticas que se nos presentaran al ser futuros ingenieros. La planificación,
mantenimiento, gestión y operación para entornos LAN, MAN y WAN para la elaboración de
Proyectos de Infraestructuras comunes de telecomunicación como por ejemplo en edificios, son
tareas que nos corresponderán en un futuro. Por ello saber realizar proyectos relacionados a la
Telemática es muy importante, ya que ahı́ utilizaremos los diversos conocimientos aprendidos en
el curso como el diseño de protocolos, como lo es UDP y las diferentes aplicaciones que le pode-
mos dar conjuntamente con diferentes dispositivos relacionados a la Ingenierı́a Electrónica. De
esta manera llevar un optimo diseño, implantación y administración de redes de computadoras
y sistemas para transmisión de datos.

2. OBJETIVO GENERAL
Diseñar e implementar un proyecto aplicando protocolo UDP y paquetes IP. Mediante
conexión a Internet.

3. OBJETIVOS ESPECÍFICOS
Establecer una conexión de datos a transmitirse al dispositivo desde el servidor.
Diseño de protocolo de comunicaciones, establecimiento de formato de paquete de nivel
de aplicación y empaquetado en UDP.

4. MATERIALES Y EQUIPO
Software Arduino
Arduino Nano
Modulo HanRun HR911105A
Conexión a Internet (RJ45)

3
5. MARCO TEÓRICO

5.1. TIEMPO UNIX

La época Unix es una fecha concreta a partir de la cual se cuentan los segundos, lo que da como
resultado una nueva medida de tiempo, es la cantidad de segundos transcurridos desde la me-
dianoche UTC del 1 de enero de 1970. Es universalmente usado no solo en sistemas operativos
tipo-Unix, sino también en muchos otros sistemas computacionales.

Hay dos capas de codificación que conforman el tiempo Unix, la primera capa codifica un
instante de tiempo como un número real escalar, y la segunda codifica ese número como una
secuencia de bits o de alguna otra manera.

5.2. BREVE RESUMEN DE UDP

Uno de los dos principales protocolos de capa de transporte utilizados en Internet y el único
servicio de transporte sin conexión es el Protocolo UDP. El protocolo de datagramas de usuario
(UDP) es un protocolo basado en el intercambio de datagramas que permite el envı́o de data-
gramas a través de la red sin que se haya establecido previamente una conexión.

Cada mensaje UDP se denomina datagrama de usuario y consta de dos partes: un encabe-
zado corto que especifica el envı́o y recepción de los programas de aplicación y una carga útil
que transporta los datos que se envı́an.[1] La figura 1 lustra el formato de datagrama del usuario.

Figura 1: El formato de un datagrama de usuario UDP

Donde:
Puerto de origen: Indica el puerto del proceso que envı́a. Este es el puerto que se direcciona
en las respuestas.
Puerto destino: Especifica el puerto del proceso destino en el host de destino.
Longitud: Es el tamaño (en bytes) de este datagrama de usuario incluyendo la cabecera.
Suma de comprobación (checksum): Es un campo opcional de 16 bits en complemento a
uno de la suma en complemento a uno de una cabecera pseudo-IP, la cabecera UDP y los
datos UDP.
La cabecera pseudo-IP contiene la dirección IP fuente y destino, el protocolo y la longitud UDP:

4
Figura 2: Ilustración del pseudo encabezado utilizado para calcular el UDP

5.3. EL ARDUINO NANO

El Arduino Nano (Figura 2) es una pequeña, pero poderosa tarjeta basada en el ATmega328.
Posee las mismas funcionalidades que un Arduino UNO, solo que en un tamaño reducido. Para
programarla solo se necesita de un cable Mini USB.

Figura 3: Arduino Nano

El Arduino Nano puede ser alimentado usando el cable USB Mini-B, con una fuente externa
no regulada de 6-20V (pin 30), o con una fuente externa regulada de 5V (pin 27). La fuente
de alimentación es seleccionada automáticamente a aquella con mayor tensión. El ATmega 328
posee 32KB, (también con 2 KB usados por el bootloader). Posee también 2 KB de SRAM y
1KB de EEPROM.[2]

Figura 4: Descripción del Arduino Nano

El Arduino Nao tiene algunos métodos para la comunicación con un PC, otro Arduino, u otros
microcontroladores. El ATmega328 poseen un módulo UART que funciona con TTL (5V)el cual
permite una comunicación vı́a serie, la cual está disponible usando los pines 0 (RX) y 1 (TX).El
ATmega328 también soporta comunicación I2C (TWI) y SPI. Para usar la comunicación SPI,
debemos mirar la hoja de datos del ATmega328.

5
5.4. MODULO HanRun HR911105A

Este Módulo Ethernet permite la conexión con una red LAN al proporcionar una comunicación
SPI al microcontrolador. La placa se alimenta a 3.3Vcc y en el conector hay todos los comandos
para administrar la interfaz.

Utiliza el Controlador Ethernet ENC28J60 de Microchip que posee las caracterı́sticas necesa-
rias para manejar los requerimientos del protocolo de red. La tarjeta incluye todo lo necesario
para el interfaz de red, incluido el conector Ethernet RJ45 con transformadores de aislamiento.
Solamente hace falta conectarla a los pines SPI y a la alimentación.

Figura 5: Modulo HanRun HR911105A

SPI es un protocolo serial sı́ncrono que se utiliza para comunicar un microcontrolador con otro
y con periféricos a distancias cortas. Para hacer una conexion SPI siempre habrá un dispositivo
maestro (usualmente un microcontrolador) que controlará uno o varios periféricos (esclavos).[3]
Por lo generar 3 lineas de conexión:

SI o MOSI (Master Out Slave In): Datos del maestro al esclavo.


SCK (Serial clock): Pulsos de reloj para sincronizar la comunicación.
CS o Select: Se usa por el master para habilitar o deshabilitar un determinado periférico.

6. DESARROLLO Y RESULTADOS

6.1. DESARROLLO DEL CÓDIGO

Para poder implementar nuestro proyecto aplicando protocolo UDP, vamos a necesitar Arduino
donde haremos uso del siguiente código:

1 # include " DS3231 . h "


# include < EtherCard .h >
3 RTClib RTC ;

5 unsigned long epoch ; // Aqui se guarda la variable de tiempo ( Unix Time )


// Ethernet mac address - must be unique on your network
7 // Genera una MAC del dispositivo

6
const byte myMac [] PROGMEM = { 0 x70 , 0 x69 , 0 x69 , 0 x2D , 0 x30 , 0 x31 };
9 const char NTP_REMOTEHOST [] PROGMEM = " 0. south - america . pool . ntp . org " ; //
Servidor Remoto
const unsigned int NTP_REMOTEPORT = 123; // Puertos de Conexion NTP
11 const unsigned int NTP_LOCALPORT = 8888; // Local UDP port to use
const unsigned int NTP_PACKET_SIZE = 48; // Paquete de 48 bytes
13 byte Ethernet :: buffer [350]; // El búfer debe ser 350 para que DHCP funcione

15 void setup () {
Serial . begin (9600) ; // Puerto Serial
17 Serial . println ( F ( " \ n [ EtherCard NTP Client ] " ) ) ;

19 // Cambie ’SS ’ a su pin Slave Select , si no está usando el pin


predeterminado INICIALIZAR
if ( ether . begin ( sizeof Ethernet :: buffer , myMac , SS ) == 0)
21 Serial . println ( F ( " Failed to access Ethernet controller " ) ) ;
if (! ether . dhcpSetup () )
23 Serial . println ( F ( " DHCP failed " ) ) ;

25 ether . printIp ( " IP : " , ether . myip ) ;


ether . printIp ( " GW : " , ether . gwip ) ;
27 ether . printIp ( " DNS : " , ether . dnsip ) ;

29 if (! ether . dnsLookup ( NTP_REMOTEHOST ) )


Serial . println ( " DNS failed " ) ;
31
uint8_t ntpIp [ IP_LEN ];
33 ether . copyIp ( ntpIp , ether . hisip ) ;
ether . printIp ( " NTP : " , ntpIp ) ;
35
ether . u d p S e r v e r L i s t e n O n P o r t (& udpReceiveNtpPacket , NTP_LOCALPORT ) ;
37 Serial . println ( " Started listening for response . " ) ;
sendNTPpacket ( ntpIp ) ;
39
}
41
void loop () {
43 // Esto debe ser llamado para que funcionen las funciones ethercard .
ether . packetLoop ( ether . packetReceive () ) ;
45 if ( epoch >1483228800) {
DateTime now = epoch ;
47 char buffer [19];
sprintf ( buffer , " %04 d / %02 d / %02 d %02 d : %02 d : %02 d " , now . year () , now . month () ,
now . day () , now . hour () , now . minute () , now . second () ) ;
49 Serial . println ( buffer ) ;
epoch = epoch +1;
51 }
delay (999) ;
53 }

55 // Enviar una solicitud NTP al servidor de tiempo en la dirección dada


void sendNTPpacket ( const uint8_t * remoteAddress ) {
57 // Búfer para mantener el paquete saliente
byte packetBuffer [ NTP_PACKET_SIZE ];
59 // Establece todos los bytes en el búfer a 0
memset ( packetBuffer , 0 , NTP_PACKET_SIZE ) ;
61 // Inicializar los valores necesarios para formar la solicitud NTP
// ( Ver URL arriba para detalles sobre los paquetes )
63 packetBuffer [0] = 0 b11100011 ; // LI , Versión , Modo
packetBuffer [1] = 0; // Estrato , o tipo de reloj

7
65 packetBuffer [2] = 6; // Intervalo de votación
packetBuffer [3] = 0 xEC ; // Precisión del reloj de pares
67 // 8 bytes de cero para el retraso de la raı́z y la dispersión de la raı́z
packetBuffer [12] = 49;
69 packetBuffer [13] = 0 x4E ;
packetBuffer [14] = 49;
71 packetBuffer [15] = 52;

73 // Todos los campos NTP han recibido valores , ahora


// Puede enviar un paquete solicitando una marca de tiempo :
75 ether . sendUdp ( packetBuffer , NTP_PACKET_SIZE , NTP_LOCALPORT , remoteAddress ,
NTP_REMOTEPORT ) ;
Serial . println ( " NTP request sent . " ) ;
77 }

79 void ud p R e ce i v eN t p Pa c k et ( uint16_t dest_port , uint8_t src_ip [ IP_LEN ] ,


uint16_t src_port , const char * packetBuffer , uint16_t len ) {
Serial . println ( " NTP response received . " ) ;
81
// La marca de tiempo comienza en el byte 40 del paquete recibido y es de
cuatro bytes ,
83 // o dos palabras , largas . Primero , extraiga las dos palabras :
unsigned long highWord = word ( packetBuffer [40] , packetBuffer [41]) ;
85 unsigned long lowWord = word ( packetBuffer [42] , packetBuffer [43]) ;
// Combina los cuatro bytes ( dos palabras ) en un entero largo
87 // Este es el tiempo NTP ( segundos desde el 1 de enero de 1900) :
unsigned long secsSince1900 = highWord << 16 | lowWord ;
89 // El tiempo de Unix comienza el 1 de enero de 1970. En segundos , eso es
2208988800:
const unsigned long seventyYears = 2208988800 UL ;
91 // Restar setenta a~ n os :
epoch = ( secsSince1900 - seventyYears ) - 18000;
93
// Imprimir el tiempo de Unix
95
}

Listing 1: Diseño del Código en Arduino

6.2. EXPLICACIÓN DE LAS PARTES MAS IMPORTANTES DEL


CÓDIGO

Para hacer el código necesitamos dos librerı́as, la primera es el EtherCard y la segunda librerı́a
es el DS3231 que es del RTC (Reloj del Tiempo Real). Un reloj de tiempo real (RTC) es un
dispositivo electrónico que permite obtener mediciones de tiempo en las unidades temporales
que empleamos de forma cotidiana.[4]

En el mundo de la electrónica casera y Arduino existen dos RTC habituales el DS1307 y el


DS3231, el DS3231 tiene una precisión muy superior y puede considerarse sustituto del DS1307,
por ello estamos usando la librerı́a RTC porque gracias a esta podemos llamar automáticamen-
te al Código Unix como una función, ya que acumularemos el tiempo Unix en una variable
llamada ”Datetime” de esa librerı́a y de ahı́ podemos sacar la fecha, la hora, el dı́a y ası́ evi-
tamos cálculos adicionales, porque para sacar la fecha tendrı́amos que hacer muchos cálculos
matemáticos y tener en cuenta la desviación del error. Cabe resaltar que no estamos usando al
RTC como deberı́a ser sino que se está acumulando datos de Internet del servidor NTP y de

8
ahı́ obtenemos toda la información.

Luego de las declaraciones de las librerı́as, creamos una variable donde se va a almacenar
la variable de tiempo (Unix Time), seguido de eso generamos una MAC para el dispositivo,
una dirección fı́sica, si no realizamos esto no se puede conectar a ningún lado porque no tiene
autentificación y ninguna red no lo podrı́a reconocer esto lo podemos ver en el Listado 2.

unsigned long epoch ;


2 // Genera una MAC del dispositivo
const byte myMac [] PROGMEM = { 0 x70 , 0 x69 , 0 x69 , 0 x2D , 0 x30 , 0 x31 };

Listing 2: Generación de la dirección MAC

Luego tenemos el Servidos Remoto (NTP) donde está incluida su dirección, sirve como cualquier
servidor NTP y es un servidor de Sudamérica para que no tenga que viajar muy lejos para traer
los datos que necesitamos. Los puertos de conexión para el NTP son el 123 (Puerto Remoto)
y el puerto local que está usando el dispositivo es el 8888, el NTP debe ser el puerto 123
obligatoriamente, porque si cambiamos este valor no nos va a responder ya que es por ese
puerto donde se envı́a el protocolo UDP. El paquete de tamaño o el paquete de recepción va
a ser de 48 bytes (48 caracteres) y el búfer de transmisión de 350 para que el servidos DHCP
funcione, este nos manda toda una cadena para que nosotros escojamos el tiempo Unix. Todo
lo explicado lo podemos ver en el Listado 3.

1 // Servidor Remoto
const char NTP_REMOTEHOST [] PROGMEM = " 0. south - america . pool . ntp . org " ;
3 const unsigned int NTP_REMOTEPORT = 123; // Puertos de Conexion NTP
const unsigned int NTP_LOCALPORT = 8888; // Local UDP port to use
5 const unsigned int NTP_PACKET_SIZE = 48; // Paquete de 48 bytes
// El búfer debe ser 350 para que DHCP funcione
7 byte Ethernet :: buffer [350];

Listing 3: Puerto Remoto y Puerto Local y Paquete de Tamaño

Es necesario inicializar el número de paquete y el búfer, es decir que el puerto de comunicación


”SS” y ”MyMAC” (MAC declarada anteriormente) hay que ponerlos a cero, si hay problemas
con el adaptador o si los cables están mal conectados nos va a mandar un error.

El Servidor que recibe peticiones de clientes solicitando una configuración de red IP es el


servidor DHCP. Este servidor responderá a dichas peticiones proporcionando los parámetros
que permitan a los clientes autoconfigurarse.[5] Cuando el sistema se conecta, automáticamente
el servidor DHCP (Protocolo de Configuración Dinámica de Host) le intenta dar una IP, eso lo
hace porque ya tiene una dirección MAC que el router reconoce. Hay una lı́nea de código donde
negamos al ”ether.dhcpSetup”, eso significa que el servidor DHCP no está presente para darle
una IP, si eso sucede nos llega un mensaje de error, pero si el Servidor DHCP si asigna un IP
lo que nos aparece es la IP brindada, la puerta de enlace y el DNS del IP, para luego intentar
conectarse al Servidor Remoto.

Posterior a eso, viene el proceso de acumulación: Primero declaramos una variable de tamaño
cuatro (4 bytes de 8 bits) y luego lo grabamos en ”ntpIp”. Finalmente imprimimos NTP y la
IP del servidor, una vez realizado esto preparamos el camino para enviar el paquete UDP y con

9
la lı́nea de código ”sendNTPpacket(ntpIp)” enviamos al servidor NTP. Generamos el paquete
de 48 bytes, grabando toda la información antes de enviarlo.

En la siguiente parte de código hacemos la petición, es decir, recién enviamos los datos de
la memoria del buffer del arduino a la memoria del modulo Ethernet.

1 ether . sendUdp ( packetBuffer , NTP_PACKET_SIZE , NTP_LOCALPORT , remoteAddress ,


NTP_REMOTEPORT ) ;
Serial . println ( " NTP request sent . " ) ;

Listing 4: Envı́o del Paquete

Luego definimos lo parámetros de llegada (Puerto destino, IP del Ethernet, pueto local, ”pac-
ketBuffer” y el tamaño de paquete) para guardar la información y empezar a discriminar esta
información haciendo diversas conversiones de tiempo.

void ud p R e ce i v eN t p Pa c k et ( uint16_t dest_port , uint8_t src_ip [ IP_LEN ] ,


uint16_t src_port , const char * packetBuffer , uint16_t len ) {
2 Serial . println ( " NTP response received . " ) ;

Listing 5: Parámetros de Llegada

Finalmente en la variable global ”epoch” guardamos toda esta información, es de cir, los datos
acumulados desde 1900 del servidor NTP y le restamos 17 años para poder sincronizar con
las fechas de ahora y luego hacemos la sincronizacion con nuestro lugar. Toda es información
pasa al bucle donde la comparamos con un numero que corresponde al 2017 (Discriminación de
tiempo), este procedimiento se hace ya que los paquetes llegan en pedazos, cuando ”epoch” lega
al 2017 recién se imprime el dato, esto lo grabamos en una variable ”DateTime” de la librerı́a
RTC para generar un buffer de 19 caracteres que nos ordene los datos en el puerto serial.Una
vez listo el paquete lo imprimimos.

}
2
void loop () {
4 // Esto debe ser llamado para que funcionen las funciones ethercard .
ether . packetLoop ( ether . packetReceive () ) ;
6 if ( epoch >1483228800) {
DateTime now = epoch ;
8 char buffer [19];
sprintf ( buffer , " %04 d / %02 d / %02 d %02 d : %02 d : %02 d " , now . year () , now . month () ,
now . day () , now . hour () , now . minute () , now . second () ) ;
10 Serial . println ( buffer ) ;
epoch = epoch +1;
12 }
delay (999) ;
14 }

Listing 6: Bucle

10
6.3. EJECUCIÓN Y RESULTADOS

Una vez ejecutado y compilado el programa realizamos las pruebas, como podemos ver en la
siguiente imagen no obtenemos ninguna dirección de ningún tipo de dato porque no tenemos
una conexión a Internet y mientras no tengamos ninguna no podremos obtener la fecha pedida
al servidor.

Figura 6: Prueba sin conexión a Internet

7. CONCLUSIONES
Logramos obtener los datos del Tiempo Unix en el puerto serial del Arduino, como la
fecha y la hora, cabe resaltar que hacer la programación principal fue algo tediosa, ya
que estamos solicitando los datos a cualquier servidor que este en Sudamérica y logramos
sincronizar estos datos con el horario de nuestra cuidad.
Hemos diseñado y armado un paquete UDP por medio del código del listado 1, pudiendo
lograr el envı́o de datagramas a través de la red sin que se haya establecido previamente
una conexión.
También es importante resaltar que trabajamos con el El Bus SPI al hacer la comunica-
ción entre el modulo Ethernet y el Microcontrolador, pudiendo controlar este dispositivo
electrónico digital para que acepte un flujo de bits serie regulado por un reloj (comunica-
ción sincrónica).

8. REFERENCIAS
1 .ComputerN etworksandInternets − DouglasE.Comer(5ta.)
2 .https : //saber.patagoniatec.com/2014/12/arduino − nano − 328 − arduino − atmega −
clon − compatible − arduino − argentina − ptec/
3 .https : //saber.patagoniatec.com/2014/10/modulo − ethernet − enc28j60 − arduino −
argentina − ptec/

11
4 .https : //www.luisllamas.es/reloj − y − calendario − en − arduino − con − los − rtc −
ds1307 − y − ds3231/
5 .http : //www.ite.educacion.es/f ormacion/materiales/85/cd/linux/m2/servidord hcp.html

12

Potrebbero piacerti anche