Capas OSI
Según la clasificación OSI, la comunicación de varios dispositivos se puede estudiar dividiéndola en 7 niveles, que son expuestos desde su nivel más alto hasta el más bajo:
Protocolo TCP/IP
El modelo TCP/IP describe un conjunto de guías generales de diseño e implementación de protocolos de red específicos para permitir que un equipo pueda comunicarse en una red. TCP/IP provee conectividad de extremo a extremo especificando como los datos deberían ser formateados, direccionados, transmitidos, enrutados y recibidos por el destinatario.
La importancia del modelo TCP/IP es que es el modelo usado para acceder a Internet o a redes internas (Intranet) de ordenadores. Arduino va a permitir conectarse a Internet o a una red interna mediante TCP/IP y poder realizar múltiples operaciones o usarse como pasarela para conectar a Internet dispositivos que no tienen esa capacidad. La implementación de la pila de protocolos de TCP/IP en Arduino se hace mediante un shield o HW adicional que nos da la capa de acceso a red (ethernet o WiFi), internet (IP) y transporte. La capa de aplicación deberemos implementarla dentro de Arduino ya sea directamente o mediante una librería.
En el caso del protocolo TCP/IP la pila OSI se simplifica:
Capa de Aplicación. |
Invoca programas que acceden servicios en la red. Interactúan con uno o más protocolos de transporte para enviar o recibir datos, en forma de mensajes o bien en forma de flujos de bytes. |
Capa de Transporte. |
Provee comunicación extremo a extremo desde un programa de aplicación a otro. Regula el flujo de información. Puede proveer un transporte confiable asegurándose que los datos lleguen sin errores y en la secuencia correcta. Coordina a múltiples aplicaciones que se encuentren interactuando con la red simultáneamente de tal manera que los datos que envíe una aplicación sean recibidos correctamente por la aplicación remota, esto lo hace añadiendo identificadores de cada una de las aplicaciones. Realiza además una verificación por suma, para asegurar que la información no sufrió alteraciones durante su transmisión. |
Capa Internet. |
Controla la comunicación entre un equipo y otro, decide qué rutas deben seguir los paquetes de información para alcanzar su destino. Conforma los paquetes IP que será enviados por la capa inferior. Desencapsula los paquetes recibidos pasando a la capa superior la información dirigida a una aplicación. |
Capa de Interfaz de Red. |
Emite al medio físico los flujos de bit y recibe los que de él provienen. Consiste en los manejadores de los dispositivos que se conectan al medio de transmisión. |
Más información en: http://www.uca.edu.sv/investigacion/tutoriales/tcp-ip.html
Conexión y desconexión TCP/IP
El proceso de establecimiento de una conexión TCP se denomina “three way handshake” Durante el establecimiento de la conexión, se configuran algunos parámetros tales como el número de secuencia con el fin de asegurar la entrega ordenada de los datos y la robustez de la comunicación.
Aunque es posible que un par de entidades finales comiencen una conexión entre ellas simultáneamente, normalmente una de ellas abre un socket en un determinado puerto TCP y se queda a la escucha de nuevas conexiones. Es común referirse a esto como apertura pasiva, y determina el lado servidor de una conexión. El lado cliente de una conexión realiza una apertura activa de un puerto enviando un paquete SYN inicial al servidor como parte de la negociación en tres pasos. En el lado del servidor (este receptor también puede ser una PC o alguna estación terminal) se comprueba si el puerto está abierto, es decir, si existe algún proceso escuchando en ese puerto, pues se debe verificar que el dispositivo de destino tenga este servicio activo y esté aceptando peticiones en el número de puerto que el cliente intenta usar para la sesión. En caso de no estarlo, se envía al cliente un paquete de respuesta con el bit RST activado, lo que significa el rechazo del intento de conexión. En caso de que sí se encuentre abierto el puerto, el lado servidor respondería a la petición SYN válida con un paquete SYN/ACK. Finalmente, el cliente debería responderle al servidor con un ACK, completando así la negociación en tres pasos (SYN, SYN/ACK y ACK) y la fase de establecimiento de conexión. Es interesante notar que existe un número de secuencia generado por cada lado, ayudando de este modo a que no se puedan establecer conexiones falseadas (spoofing).
Más información:
La fase de finalización de la conexión utiliza una negociación en cuatro pasos (four-way handshake), terminando la conexión desde cada lado independientemente. Sin embargo, es posible realizar la finalización de la conexión en 3 fases; enviando el segmento FIN y el ACK en uno solo. Cuando uno de los dos extremos de la conexión desea parar su «mitad» de conexión transmite un segmento con el flag FIN en 1, que el otro interlocutor asentirá con un ACK. Por tanto, una desconexión típica requiere un par de segmentos FIN y ACK desde cada lado de la conexión.
Una conexión puede estar «medio abierta» en el caso de que uno de los lados la finalice pero el otro no. El lado que ha dado por finalizada la conexión no puede enviar más datos pero la otra parte si podrá.
Es importante conocer este apartado porque a pesar que esta negociación la hace el shield de Ethernet o Wifi y no se programa en Arduino, sirve para saber qué está pasando cuando Arduino actúa como cliente o servidor y poder hacer depuración cuando tenemos errores.
Librería Ethernet
La librería Ethernet es la usada para manejar el Ethernet Shield que implementa la pila de protocolos TCP/IP y dentro de Arduino se implementan los protocolos en la capa de aplicación. La librería se usa entre otras cosas para mandar por Ethernet el protocolo programado en Arduino.
Para manejar el Ethernet Shield deberemos conocer todos los métodos que nos ofrece la librería Ethernet y así poder usarla.
Reference de librería Ethernet: http://arduino.cc/en/Reference/Ethernet
La librería ethernet se compone de 5 clases, cada una con sus métodos
Ethernet Class
Inicializa la librería ethernet y las configuraciones de red.
- begin() – Inicializa la librería Ethernet (Constructor)
- localIP() – Obtiene la dirección IP. Útil al usar DHCP
- maintain() – Solicita una renovación al servidor DHCP
IPAddress Class
Trabaja con IPs locales y remotas. Facilita el trabajo con direcciones IPs.
Server Class
Crea un servidor que puede mandar y recibir datos de los clientes conectados.
- Server() – Constructor de la clase server. No se usa directamente
- EthernetServer() – Crea un servidor que escucha por las conexiones entrantes del puerto definido.
- begin() – Le dice al servidor que comience a escuchar.
- available() – Devuelve el cliente que está conectado al servidor y tiene datos disponibles a leer.
- write() – Escribe datos a todos los cliente conectados al servidor.
- print() – Escribe datos a todos los cliente conectados al servidor.
- println() – Escribe datos a todos los cliente conectados al servidor seguido de una nueva línea.
Client Class
Crea un cliente que se conecta a un servidor y puede mandar y recibir datos.
- Client – Constructor de la clase client. No se usa directamente
- EthernetClient() – Crea un cliente que se conecta a una determinada IP y puerto
- if (EthernetClient) – Indica si el cliente Ethernet está preparado
- connected() – Devuelve si el cliente está o no conectado
- connect() – Conecta a una IP y puerto especificado. Soporta DNS lookup. Devuelve unos códigos en función del éxito o fallo de la conexión.
- write() – Escribe datos al servidor al que está conectado.
- print() – Escribe datos al servidor al que está conectado
- println() – Escribe datos al servidor al que está conectado, seguido de una nueva línea
- available() – Devuelve el número de bytes disponibles para leer.
- read() – Lee el siguiente byte recibido desde el servidor.
- flush() – Borrar todos los bytes que han sido escritos en el cliente pero no leidos
- stop() – Desconecta el cliente del servidor
Arduino nos ofrece varios ejemplo para comprender el uso de la librería:
Protocolo HTTP
Hypertext Transfer Protocol o HTTP (en español protocolo de transferencia de hipertexto) es el protocolo de comunicación que permite las transferencias de información en la WWW. Se trata de un protocolo de capa 7 de aplicación.
En arduino con la librería ethernet solo trabajamos con la capa de aplicación, todas las otras capas de TCP/IP ya están implementadas por Hardware, ya sea con la ethernet shield o el módulo WiFi. Aunque si queremos realizar algunas funciones de capas inferiores, podemos hacerlo con los comandos adecuados comunicándonos con el chip ethernet o wifi via SPI.
HTTP define la sintaxis y la semántica que utilizan los elementos de software de la arquitectura web (clientes, servidores, proxies) para comunicarse. Es un protocolo orientado a transacciones y sigue el esquema petición-respuesta entre un cliente y un servidor. Al cliente que efectúa la petición (un navegador web) se lo conoce como «user agent» (agente del usuario). A la información transmitida se la llama recurso y se la identifica mediante un localizador uniforme de recursos (URL).
HTTP es un protocolo sin estado, es decir, que no guarda ninguna información sobre conexiones anteriores. El desarrollo de aplicaciones web necesita frecuentemente mantener estado. Para esto se usan las cookies, que es información que un servidor puede almacenar en el sistema cliente. Esto le permite a las aplicaciones web instituir la noción de «sesión», y también permite rastrear usuarios ya que las cookies pueden guardarse en el cliente por tiempo indeterminado.
Una transacción HTTP está formada por un encabezado seguido, opcionalmente, por una línea en blanco y algún dato. El encabezado especificará cosas como la acción requerida del servidor, o el tipo de dato retornado, o el código de estado. El uso de campos de encabezados enviados en las transacciones HTTP le dan gran flexibilidad al protocolo. Estos campos permiten que se envíe información descriptiva en la transacción, permitiendo así la autenticación, cifrado e identificación de usuario. Ejemplos de encabezados: HTTP_ACCEPT y HTTP_USER_AGENT.
Líneas de encabezado o headers, son muy importantes y dan información adicional de la conexión y el comportamiento puede cambiar en función de ellas:
Métodos de petición HTTP
Lo más importante para comunicar arduino por HTTP con otros dispositivos, ya sean servidores, ordenadores, otros Arduinos, etc… es conocer los métodos GET y POST del protocolo HTTP. HTTP define 8 métodos que indica la acción que desea que se efectúe sobre el recurso identificado. Lo que este recurso representa, si los datos pre-existentes o datos que se generan de forma dinámica, depende de la aplicación del servidor. A menudo, el recurso corresponde a un archivo o la salida de un ejecutable que residen en el servidor.
GET
GET: Pide una representación del recurso especificado. Por seguridad no debería ser usado por aplicaciones que causen efectos ya que transmite información a través de la URI agregando parámetros a la URL. La petición puede ser simple, es decir en una línea o compuesta de la manera que muestra el ejemplo.
Ejemplo:
GET /images/logo.png HTTP/1.1 obtiene un recurso llamado logo.png
Ejemplo con parámetros:
/index.php?page=main&lang=es
POST
POST: Envía los datos para que sean procesados por el recurso identificado. Los datos se incluirán en el cuerpo de la petición. Esto puede resultar en la creación de un nuevo recurso o de las actualizaciones de los recursos existentes o ambas cosas.
Más información:
Entender los métodos get y post:
Un explicación muy buena de HTTP también se puede encontrar en: http://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html
HTTP request
Un cliente HTTP debe formar una petición HTTP al servidor de una forma determinada para que sea entendida por el servidor. Cuando Arduino trabaja como cliente hay que programar esta petición correctamente.
Formación de un HTTP request, esta petición habrá que programar en Arduino:
Trama en HTTP, fijaros en el uso de cr (retorno de carro – carriage return – ASCII 13) y lf (line feed – nueva linea – ASCII 10): http://www1.ju.edu.jo/ecourse/abusufah/cpe532_Spr06/notes/BookOnLine/HTTP%20Request%20Message.htm
HTTP/1.1 se definió en el estándar RFC2616,que es la más usada actualmente. En junio de 2014 RFC2616 se retiró y HTTP/1.1 se redefinió en RFCs 7230, 7231, 7232, 7233, 7234, and 7235, HTTP/2 está en proceso de definición.
Y cuando usar GET o POST?: http://www.w3.org/2001/tag/doc/whenToUseGet.html#checklist
HTTP response
Después de recibir e interpretar el servidor un HTTP request, el servidor debe responder con un mensaje de respuesta:
Para cumplir con el protocolo HTTP, arduino debe implementar estas respuestas cuando lo uso como servidor web.
Veamos esto gráficamente:
Práctica: Comunicaciones IP
Ver diferencia de configuración en Arduino entre DHCP e IP fija:
Realizar las prácticas de Arduino Web Client: https://aprendiendoarduino.wordpress.com/2016/07/05/arduino-web-client/
Realizar las prácticas de Arduino Web Server: https://aprendiendoarduino.wordpress.com/2016/07/06/arduino-web-server/