El protocolo de colas de mensajes STOMP

El presente artículo es una explicación basada en el ‘Stomp Protocol Specification, Version 1.0’ publicado por Codehaus en http://stomp.codehaus.org/Protocol.

1. El protocolo STOMP

El protocolo STOMP de colas de mensajes se utiliza para comunicación distribuida entre computadoras, principalmente en aplicaciones de informática. STOMP es el Protocolo de Mensajes Orientado a Texto y en Flujos (Streaming Text Oriented Messaging Protocol). Esto significa que los mensajes que se pueden crear y enviar por un lado, y recibir y procesar por el otro lado son mensajes de texto; puede ser cualquier documento de texto: plano, yaml, json, xml, etc. También significa que los mensajes se envían y reciben dentro de un flujo de datos, dicho de otra manera, mensajes van y mensajes vienen dentro de un mismo contexto de conexión.

Los servicios de colas de mensajes son utilizados desde hace mucho tiempo en aplicaciones dentro de bancos, empresas de telecomunicaciones y algunas otras industrias. Tienen mucha aplicación en la informática porque permiten una forma de computación distribuida con bajo acoplamiento, además es fácil de entender porque presenta un patrón de tipo productor-consumidor. Un caso fácil de entender sacado de morethanseven es cuando una web solicita información al cliente y cuando el cliente pulsa el botón de enviar la web le envía un correo electrónico, digamos con un resumen de su petición; si llegan muchos usuarios a enviar el formulario, el servidor se pondrá lento enviando correos, mientras que los usuarios irán notando que la página se vuelve lenta; esto ocurre porque el envío de correo toma un poco de tiempo y el servidor de web es quien está enviando cada correo (con la ayuda del servidor de correos).

Servidor de Colas
Servidor de Colas

Ahora, si en vez de que el servidor web envíe el mensaje directamente al servidor de correo, lo coloca en una cola, esta cola a su vez está en un servidor aparte, y luego de dejar el mensaje en cola el servidor web muestra una respuesta al usuario liberandose para los demás usuarios que envíen el formulario. Esto haría que el servidor web no se ponga lento tan rápido. Pero ¿qué pasa con el mensaje? aún no se ha enviado por correo. Es cierto, el mensaje está en una cola en un servidor de colas, pero no se queda allí, porque la magia del servidor de colas es que este despacha el mensaje a un servicio que está procesando los mensajes de la cola, y ese servicio si va a enviar el correo: toma el mensaje de la cola y lo manda por correo; si llegan muchos mensajes, no importa, el servidor de colas de mensajes los va agregando al final de la cola y va despachando uno a uno según el proceso que los consume los pueda ir tomando y enviando sin saturar los recursos ni del servidor de correos y menos del servidor web.

Entonces el sistema es muy sencillo, un proceso escribe mensajes en el servidor, el servidor los mete en una cola y los va despachando hacia otro proceso que los va consumiendo según tenga disponibilidad de recursos.

Existen otros protocolos de mensajes como XMPP, SMTP o JMS para nombrar solo algunos y dejar por fuera mucho más. STOMP es un protocolo sencillo y ligero, por lo tanto está condenado al éxito y a ser usado en muchas aplicaciones que requieran sencillez y facilidad de uso. A partir de este punto se va a explicar el funcionamiento del protocolo STOMP basado en la propia especificación del protocolo.

2. El cliente se conecta con el servidor STOMP.

Lo primero que debe hacer el cliente es abrir un socket al servidor. Es conveniente asumir que la conexión será con TCP ya que es lo más común y los servidores están hechos así. Para conectarse, un cliente debe enviar la siguiente trama:

CONNECT
login:usuario
passcode:clavesecreta

^@

El símbolo ^@ es un byte null (control-@ en ASCII). Se usa para definir el fin de mensaje. Toda trama inicia con un comando (en este caso CONNECT que significa conectar) en una línea, siguen los encabezados en forma ‘clave:valor’ cada uno en su propia línea (login y passcode en este ejemplo), se deja una línea en blanco y luego viene el cuerpo del mensaje, el cual termina con el byte ^@ (en este caso el cuerpo del mensaje está en blanco). El encabezado ‘login’ (entrar) se usa para enviar el usuario que se conecta, mientras que passcode (código de pase) se usa para enviar la clave secreta. Para separar las líneas se usa un caracter de nueva línea al final de cada línea.

Luego que el cliente envía la trama CONNECT el servidor responde con la siguiente trama:

CONNECTED
session:identificador de sesión

^@

CONNECTED significa conectado. El encabezado session es un identificador que puede ser cualquier texto con tal que sea distinto para cada conexión que se haga con el servidor (la especificación lo manda, pero no es usado para nada actualmente; en el futuro puede ser usado en otras tramas).

Ya con esto se establece una conexión al servidor y se pueden realizar varias acciones, cada una con su trama:

  • SEND – Enviar. Enviar mensajes a una cola en el servidor.
  • SUBSCRIBE – Suscribirse. Suscribirse para recibir mensajes que otros pongan en una cola.
  • UNSUBSCRIBE – Desuscribirse. Dejar de recibir mensajes que otros pongan en una cola.
  • BEGIN – Iniciar. Inicia una transacción.
  • COMMIT – Comprometer. Compromete (ejecuta definitivamente) las acciones que se hicieron en una transacción.
  • ABORT – Abortar. Deshacer las acciones hechas en una transacción.
  • ACK – Confirmación (Acknowledge). Confirma la recepción de un mensaje por parte del proceso que lo consume.
  • DISCONNECT – Desconectar. Para terminar una conexión con el servidor.

Entonces lo primero es conectarse, luego se pueden enviar o consumir muchos mensajes, dependiendo del lado donde esté el proceso (en el lado que pone mensajes o en el lado que los consume) y finalmente en algún momento se cierra la conexión. Esta es la parte de flujos del protocolo, como se puede ver todo ocurre dentro de un flujo de mensajes que van y vienen entre el servidor y los clientes que ponen mensajes y que consumen mensajes.

3. Comandos que pueden enviar los clientes.

SEND.

Significa enviar. Sirve para enviar o colocar mensajes hacia un destino en el servidor. Este lo usa el cliente que quiere poner un mensaje en una cola. Tiene un encabezado requerido: destination (destino) que indica donde se va a enviar el mensaje. El cuerpo de la trama SEND es el mensaje que se quiere enviar. Ejemplo:

SEND
destination:/cola/mensajes

Texto del mensaje puesto en la cola
^@

Esto envía el mensaje ‘Texto del mensaje puesto en la cola’ a la cola llamada ‘/cola/mensajes’. El nombre de la cola es totalmente arbitrario; en este ejemplo se usó la palabra ‘cola’ pero en el servidor no necesariamente es una cola, puede ser otra cosa que el servidor quiera implementar, no hay nada que obligue al servidor a usar una cola. Los nombres en ‘destination’ (destino) únicamente identifican un lugar en el servidor para poner los mensajes, cada nombre indica un lugar distinto, cada servidor puede implementar este mecanismo como quiera.

Las tramas SEND soportan un encabezado ‘transaction’ (transacción) que sirve para enviar el mensaje en el contexto de una transacción.

Se recomienda que las tramas SEND incluyan un encabezado ‘content-length’ (longitud del contenido) que es el número de bytes del cuerpo del mensaje. Esto sirve cuando el mensaje incluye caracteres de null (^@); si no se incluye un content-length el servidor tomará el mensaje hasta el primer null que encuentre e ignorará el resto del mensaje; por el contrario si tiene content-length el servidor leerá esa cantidad de bytes del mensaje, incluyendo los bytes que sean null (^@).

SUBSCRIBE

Significa suscribir. Se usa para registrar que se quieren consumir mensajes de un destino (‘destination’) dentro del servidor; por ejemplo consumir mensajes de una cola. Al igual que la trama SEND, la trama SUBSCRIBE requiere un encabezado ‘destination’ (destino) para indicar la cola a la que se quiere suscribir. De esa forma, cualquier mensaje que se reciba en la cola (porque otro proceso puso el mensaje) será enviado desde el servidor al proceso cliente que se suscribió a la cola como una trama MESSAGE (mensaje). Se puede colocar un encabezado ‘ack’ (confirmar, acknowledge), pero es opcional y si no se coloca el valor es ‘auto’. Ejemplo:

SUBSCRIBE
destination:/cola/mensajes
ack:client

^@

En este ejemplo el encabezado ‘ack’ (confirmar) está en ‘client’ (cliente) lo que significa que el mensaje será considerado como enviado al proceso cliente cuando el proceso cliente envíe al servidor una trama ACK (confirmación). Los valores válidos para el encabezado ‘ack’ son ‘auto’ (automático, que es el que se asume por defecto si no se manda encabezado ‘ack’) y ‘client’ (cliente).

El cuerpo de las tramas SUBSCRIBE (suscribir) es ignorado completamente.

Se puede agregar un encabezado ‘id’ (identificador) que podrá ser usado luego en una trama UNSUBSCRIBE (desuscribir), de esa forma, si un proceso tiene varias suscripciones a un mismo ‘destination’ (destino), puede elegir a cual de-suscribirse porque le asignó distinto ‘id’ (identificador) a cada proceso. Si se indica un encabezado ‘id’ entonces el servidor deberá agregar a su vez un encabezado ‘subscription’ (suscripción) a las tramas MESSAGE (mensaje) que él envía al cliente suscrito, de forma que el cliente podrá saber exactamente a cual suscripción se refiere la trama MESSAGE (mensaje). Si el servidor soporta comodines (wildcards) y selectores (selectors) el ‘id’ puede servir a los clientes de ayuda para saber cual suscripción originó el mensaje. Los comodines y selectores se explican más abajo. El servidor podría soportar un encabezado ‘selector’ que puede contener un selector de tipo SQL 92 como se explica hacia el final del artículo.

UNSUBSCRIBE

Significa de-suscribir. Esta trama se utiliza para remover una suscripción existente de forma que ya no se reciban más mensajes provenientes del destino (destination) al que previamente se suscribió. Requiere uno de estos dos encabezados: ‘destination’ (destino) o ‘id’ (identificador). Para usar el encabezado ‘id’ tuvo que haberse pasado también al momento de hacer la suscripción. Ejemplo:

UNSUBSCRIBE
destination:/cola/mensajes

^@

BEGIN

Significa iniciar. Se usa para iniciar una transacción. Las transacciones en este protocolo solo aplican a envío de mensajes y confirmación de recepción de mensajes. Cualquier mensaje enviado o al que se le confirme su recepción será manejado atómicamente durante la transacción. Ejemplo:

BEGIN
transaction:identificador

^@

El encabezado ‘transaction’ (transacción) es requerido y se refiere a un identificador que deberá ser usado en las tramas SEND, COMMIT, ABORT y ACK para indicar que están asociadas a la transacción por el nombre dado en el identificador.

COMMIT

Significa comprometer. Se usa para ejecutar definitivamente una transacción en curso, es decir, para indicar que la transacción terminó exitosamente y deben ejecutarse atómicamente todos comandos enviados desde el BEGIN. Ejemplo:

COMMIT
transaction:identificador

^@

El encabezado ‘transaction’ (transacción) es requerido y se refiere al identificador que se indicó al iniciar la transacción con la trama BEGIN.

ACK

Significa confirmar (acknowledge). Se utiliza para confirmar la recepción y consumo de un mensaje de parte del cliente, cuando el tipo de confirmación es ‘client’ (cliente). Cuando un cliente envía una trama SUBSCRIBE (suscribir) con un encabezado ‘ack’ (confirmación, acknowledge) con valor ‘client’ (cliente) entonces para que el servidor considere que el cliente ha consumido el mensaje, el cliente debe enviar una trama ACK de confirmación.

ACK tiene el encabezado ‘message-id’ (identificador del mensaje) como requerido, y el identificador debe coincidir con el que envía el servidor en la trama MESSAGE (mensaje) correspondiente para ser confirmada. Adicionalmente un encabezado ‘transaction’ (transacción) puede ser usado para indicar que la trama está dentro de una transacción. Ejemplo:

ACK
message-id:identificador
transaction:numero de transacción

^@

El encabezado ‘transaction’ es opcional.

ABORT

Significa Abortar. Se usa para indicar que se debe abortar o rechazar una transacción en curso. Es decir, que ningún mensaje dentro de la transacción debe ser enviado. Ejemplo:

ABORT
transaction:numero de transacción

^@

El encabezado ‘transaction’ (transacción) es requerido para identificar la transacción.

DISCONNECT

Significa desconectar. Se usa para desconectarse limpiamente del servidor. Es adecuado hacer una desconexión antes de cerrar el socket TCP. Ejemplo:

DISCONNECT

^@

4. Encabezados estándar.

Algunos encabezados pueden ser usados en la mayoría de las tramas y tienen un significado especial.

receipt

Significa recibo. Cualquier trama que envíe el cliente menos CONNECT puede hacer uso del encabezado ‘receipt’ con un valor arbitrario. Esto hará que el servidor confirme la recepción de la trama enviando al cliente una trama RECEIPT que contendrá el valor del este encabezado en el encabezado ‘receipt-id’ de la trama RECEIPT. Ejemplo:

SEND
destination:/cola/mensajes
receipt:mens876

Mensaje con confirmación de recibo.
^@

5. Tramas del servidor

El servidor enviará también tramas al cliente, adicional a la trama CONNECTED (conectado) que envía al momento de la conexión puede enviar también:

  • MESSAGE
  • RECEIPT
  • ERROR

MESSAGE

Significa mensaje. Estas tramas se usan para enviar los mensajes de las suscripciones a los clientes suscritos. Las tramas MESSAGE contienen un encabezado ‘destination’ (destino) indicando la cola destino que recibió el mensaje. También contendrá un encabezado ‘message-id’ (identificador del mensaje) con un identificador único. El cuerpo de la trama contiene el mensaje. Ejemplo:

MESSAGE
destination:/cola/de/ejemplo
message-id:identidad9001

Este es el mensaje^@

Se recomienda que las tramas MESSAGE incluyan un encabezado ‘content-lenght’ (longitud del contenido) con una cuenta de los bytes del cuerpo de la trama. Si viene el encabezado ‘content-length’ entonces se leerán esa cantidad de bytes. Esto permite tener caracteres null en el cuerpo del mensaje.

RECEIPT

Significa recibo. El servidor envía tramas de recepción cuando el cliente ha especificado un encabezado ‘receipt’ en algún comando. La trama RECEIPT contiene un encabezado ‘receipt-id’ que contiene el mismo que vino en el encabezado ‘receipt’ que envió el cliente. Ejemplo:

RECEIPT
receipt-id:mens876

^@

El cuerpo del mensaje debe estar vacío.

ERROR

El servidor podría enviar tramas ERROR si algo va mal. Las tramas de error contendrán un encabezado ‘message’ (mensaje) con una breve descripción del error, el cuerpo podrá contener todos los detalles del error o venir vacío. Ejemplo:

ERROR
message:trama no reconocida

El mensaje:
-----------
COLA
destination:colademensajes

Datos del mensaje
-----------
no contiene un comando válido del protocolo STOMP.
^@

Se recomienda que las tramas ERROR incluyan un encabezado ‘content-lenght’ (longitud del contenido) con una cuenta de los bytes del cuerpo de la trama. Si viene el encabezado ‘content-length’ entonces se leerán esa cantidad de bytes. Esto permite tener caracteres null en el cuerpo del error.

6. Comodines (wildcards)

Esta sección es una explicación basada en la página de Apache ActiveMQ sobre Wildcards de The Apache Software Foundation ubicada en http://activemq.apache.org/wildcards.html.

El soporte de comodines sirve para suscribirse en un solo comando SUBSCRIBE a varias colas. Un ejemplo clásico de esto es cuando existen varias colas cada una de las cuales lleva el control de los cambios de precios de una acción en particular, entonces se tendrían varias colas como por ejemplo:

  1. bolsavalores/rentavariable/MPA
  2. bolsavalores/rentavariable/CRM.A
  3. bolsavalores/rentavariable/MVZ.A
  4. bolsavalores/rentavariable/MVZ.B

Si se quiere que una sola suscripción consuma todas las colas de acciones clase A (CRM.A y MVZ.A) entonces puede suscribirse con el siguiente comodín:

SUBSCRIBE
destination:bolsavalores/rentavariable/*.A

^@

Se observa que el * significa que puede haber cualquier texto en ese lugar.

En otro ejemplo un proceso quiere suscribirse para consumir todas las colas de renta variable, puede hacer así:

SUBSCRIBE
destination:bolsavalores/rentavariable/>

^@

En este caso el símbolo > (mayor que) significa que puede haber cualquier texto de allí en adelante.

Entonces:

  • El símbolo * singnifica que puede coincidir con cualquier texto. Se usa para coincidir un trozo del nombre de la cola.
  • El símbolo > significa que puede coincidir cualquier texto que siga a partir de allí. Se usa para coincidir todas las colas en una jerarquía.

7. Selectores

Esta sección es una explicación basada en la página de Apache ActiveMQ sobre Selectors de The Apache Software Foundation ubicada en http://activemq.apache.org/selectors.html.

Los selectores se utilizan para recibir únicamente algunos mensajes de una suscripción y no todos. Normalmente se reciben todos los mensajes que llegan a una cola a la que se está suscrito, pero si se usan selectores se podrían filtrar algunos mensajes.

Los selectores utilizan sintaxis de SQL 92 y solo se pueden usar claves del encabezado, por ejemplo:

SUBSCRIBE
destination:/mi/cola/con/muchosMensajes
selector:id = 'cola080' and ack='client'

^@

Los selectores no pueden usarse con el cuerpo del mensaje, solo con los encabezados.

8. Algunos enlaces

Copyright 2010. Camilo Torres.

Licencia  Creative Commons
Este obra está bajo una licencia Creative Commons Reconocimiento 3.0 Unported.

Nokia CS-15 de Digitel BAN en Debian

En estos días un usuario de la lista de Ubuntu-ve hizo unos comentarios sobre su nuevo modem Nokia CS-15 con el servicio BAN de Digitel. La caja del modem indica que soporta Linux, lo cual es cierto.

El usuario hizo este par de comentarios:

Ya por fin hoy me compre un BAM (Digitel) modelo Nokia
CS-15 , Llamo mi atencion, porque en la caja del producto dice que
funciona en Windows, MacOSX , y Linux ! Dice ( siempre que poseas un
kernel 2.6.18 o posterior ) “Simple Instalacion … Plug and Play” ,
pero como estaremos ya acostumbrados… no es del todo cierto… de
hecho uso Karmic Koala, actualizado al dia… y al conectarlo… no
sucedio absolutamente nada

yo conecté el modem y no paso nada en lo absoluto (pero NADA)… ni como USB mass storage, ni como modem , ni como cdroom, NADA… se que el admin de conexiones viene con digitel por default para venezuela, pero intete correrlo y tampoco pasó nada

Como mi correo está moderado en la lista de Ubuntu-ve, creo que mi respuesta nunca llegó a la lista (creo que no llega ninguna de las que he dado últimamente); entonces tengo una justificación para volver a escribir en el blog, que tenía tiempo descuidado. A este (y otros usuarios del Nokia CS-15) le diría:

1. Si lo podrás usar. Estoy posteando este correo con el modem Nokia CS-15 con el servicio de Chimbitel. Es lento, pero estable (no se cae a cada rato ni en horas pico, movo Choristar).

2. El modem está diseñado para que sea Pulg & Play en Guindows. Al montar el dispositivo se supone que Guindows lo reconoce como un CD-ROM y ejecuta el instalador. Pero en linux no monta porque simplemente da un error leyendo un sector o algo así (ya no recuerdo). Entonces, cuando conectas el modem al USB este no se monta como un modem, sino como un dispositivo de almacenamiento.

3. Lo que necesitas es montar el dispositivo como modem. Las instrucciones y el paquete para hacerlo está en el mismo dispositivo, pero como no lo puedes montar, es como si no lo tuvieras. Bájalo de la página de Nokia:
http://europe.nokia.com/support/product-support/internet-stick-cs-15-support/software Esta dirección es errada
http://mea.nokia.com/support/product-support/internet-stick-cs-15/software

No podrás instalar ese paquete .deb, porque tiene un error (no lo intentes instalar con dpkg -i, porque luego vas a tener que hacer una brujería). Pero no importa, descomprime el paquete en un directorio.

4. Copia el archivo etc/udev/rules.d/25-nokia-zerocd.rules en etc/udev/rules.d/ como root:
sudo cp etc/udev/rules.d/25-nokia-zerocd.rules etc/udev/rules.d/

5. Copia los archivos lib/udev/* en /lib/udev/ como root:
sudo cp lib/udev/* /lib/udev/

6. Recarga las reglas de udev para que gnu/linux haga el cambio solo del modem a modo modem:
sudo udevadm control –reload-rules

Para conocimiento de todos, en el script original del paquete esta parte está mal y por eso falla. Me di cuenta yo mismo y luego lo confirme con búsquedas y comentarios de usuarios en internet. El script dice ‘udevadm control reload_rules’, y ese reload_rules no es reconocido como un comando de control, lo correcto (al leer la doc) es –reload-rules. Los de nokia parecen flojos con esto…

7. Búscate un celular Chimbitel, ponle el chip del modem y quítale el código PIN para que no te lo pida cuando prendas el celular con ese chip puesto. Cada celular tiene una opción para que no pida el PIN cada vez que se prende el celular.

8. Abre una terminal o consola y monitorea el archivo de log de mensajes:
sudo tail -f /var/log/messages.

9. Puya el celular en el puerto USB, y verás que el log de mensajes intentará montar el dispositivo como mass storage device (un disco externo), pero luego lo desmonta y lo monta como modem USB y te crea 2 dispositivos: /dev/ttyACM0 y /dev/ttyACM1. Si hace esto, mi pana, ya estás casi listo.

10. Corre el archivo de configuración de PPP: sudo pppconfig. Crea una nueva conexión llamada digitel guiándote por lo datos que aparecen en la página:
http://dk-linux.blogspot.com/2009/08/digitel-bam-3g-en-debian.html
Debes saber que esa página no usa PPP sino wvdial para conectarse, así que solo guíate de los datos de conexión de Digitel.

11. Luego edita el archivo /etc/chatscripts/digitel y dejalo así:
# This chatfile was generated by pppconfig 2.3.18.
# Please do not delete any of the comments. Pppconfig needs them.
#
# ispauth CHAP
# abortstring
ABORT BUSY ABORT ‘NO CARRIER’ ABORT VOICE ABORT ‘NO DIALTONE’ ABORT ‘NO DIAL TONE’ ABORT ‘NO ANSWER’ ABORT DELAYED
# modeminit
” ATZ
#agregado por camilo:
#” ATZ+CPIN=”0000″
#OK ‘ATQ0 V1 E1 +FCLASS=0’
OK ‘AT+CGDCONT=1,”IP”,”gprsweb.digitel.ve”‘
#fin agregado por camilo.
# ispnumber
OK-AT-OK “ATDT*99#”
# ispconnect
CONNECT \d\c
# prelogin

# ispname
# isppassword
# postlogin

# end of pppconfig stuff

12. Luego de tener configurado PPP para conectar con Digitel, escribe en una consola o terminal: sudo pon digitel.
Deberías ver en la consola donde hiciste sudo tail -f /var/log/messages un mensaje de conexión parecido a este:
Apr 17 08:11:05 cubagua pppd[4154]: pppd 2.4.4 started by root, uid 0
Apr 17 08:11:06 cubagua chat[4156]: abort on (BUSY)
Apr 17 08:11:06 cubagua chat[4156]: abort on (NO CARRIER)
Apr 17 08:11:06 cubagua chat[4156]: abort on (VOICE)
Apr 17 08:11:06 cubagua chat[4156]: abort on (NO DIALTONE)
Apr 17 08:11:06 cubagua chat[4156]: abort on (NO DIAL TONE)
Apr 17 08:11:06 cubagua chat[4156]: abort on (NO ANSWER)
Apr 17 08:11:06 cubagua chat[4156]: abort on (DELAYED)
Apr 17 08:11:06 cubagua chat[4156]: send (ATZ^M)
Apr 17 08:11:06 cubagua chat[4156]: expect (OK)
Apr 17 08:11:06 cubagua chat[4156]: ATZ^M^M
Apr 17 08:11:06 cubagua chat[4156]: OK
Apr 17 08:11:06 cubagua chat[4156]: — got it
Apr 17 08:11:06 cubagua chat[4156]: send (AT+CGDCONT=1,”IP”,”gprsweb.digitel.ve”^M)
Apr 17 08:11:07 cubagua chat[4156]: expect (OK)
Apr 17 08:11:07 cubagua chat[4156]: ^M
Apr 17 08:11:07 cubagua chat[4156]: AT+CGDCONT=1,”IP”,”gprsweb.digitel.ve”^M^M
Apr 17 08:11:07 cubagua chat[4156]: OK
Apr 17 08:11:07 cubagua chat[4156]: — got it
Apr 17 08:11:07 cubagua chat[4156]: send (ATDT*99#^M)
Apr 17 08:11:07 cubagua chat[4156]: expect (CONNECT)
Apr 17 08:11:07 cubagua chat[4156]: ^M
Apr 17 08:11:07 cubagua chat[4156]: ATDT*99#^M^M
Apr 17 08:11:07 cubagua chat[4156]: CONNECT
Apr 17 08:11:07 cubagua chat[4156]: — got it
Apr 17 08:11:07 cubagua chat[4156]: send (\d)
Apr 17 08:11:08 cubagua pppd[4154]: Serial connection established.
Apr 17 08:11:08 cubagua pppd[4154]: Using interface ppp0
Apr 17 08:11:08 cubagua pppd[4154]: Connect: ppp0 /dev/ttyACM0
Apr 17 08:11:08 cubagua pppd[4154]: Remote message: TTP Com PPP – Password Verified OK
Apr 17 08:11:08 cubagua pppd[4154]: PAP authentication succeeded
Apr 17 08:11:09 cubagua pppd[4154]: local IP address 10.252.167.182
Apr 17 08:11:09 cubagua pppd[4154]: remote IP address 10.0.0.1
Apr 17 08:11:09 cubagua pppd[4154]: primary DNS address 10.99.0.11
Apr 17 08:11:09 cubagua pppd[4154]: secondary DNS address 204.59.152.208

13. Ya estás conectado y podrás navegar. Para desconectarte primero escribe: sudo poff digitel, luego puedes desconectar el model (observa siempre el log para que veas que ya se ha desconectado).

Finalmente comento que desde ese momento hasta hoy ha corrido agua bajo el río. Dejé de usar el modem porque el servicio es muy lento y me aburrí de él.

Más censura en la Wikipedia: Venenux

Al hacer una búsqueda por Internet se puede observar que hay muchas quejas de censura en la Wikipedia. Ellos utilizan este lema: la enciclopedia libre. Luego de investigar he notado que no es tan libre y que si hay censura. La última víctima de la que me he enterado es la distro Venenux.

Esta distro es latinoamericana y se originó en Venezuela, es una muy buena distro basada en Debian. Es estable y tiene muchos paquetes, incluso muchos que no están en Debian. Es ligera y se puede usar cómodamente porque usa el escritorio KDE 3.5. Como muchas otras distros le pusieron una página o entrada en la Wikipedia, entrada que fue borrada recientemente, según el censor, por ser ‘propaganda’ de la distro.

Venenux merece nuestro apoyo porque, a parte de ser una distro muy buena, es una distro nuestra. Si estás usando una distro que corre leeento, que se chupa toooda la memoria, entonces cámbiate a Venenux.

Tableta Digital Genius Mousepen 8×6

La tabla digital
tableta digitalPuse a funcionar la tableta Mousepen 8×6 de la empresa Genius. Mi sistema es Debian Testing (Squeeze) AMD64. Para esta arquitectura no hay driver compilado, por lo que tuve que bajarlo y compilarlo, lo cual resultó muy sencillo.

El driver
Solo hay que descargar el driver wizardpen, mejor si es la última versión que es la 0.7-alpha2, y seguir las instrucciones de compilación que están para Ubuntu, pero funcionan igualitas en Debian. Asegurese de hacer ‘sudo make install’ en vez de solo ‘make install’ para que se instale sin problemas.

La configuración en Debian
Luego viene la parte de configuración, que es la emocionante. Se conecta la tabla digital y se escribe:

cat /proc/bus/input/devices | grep Name

Lo que arroja:

...
N: Name="UC-LOGIC Tablet WP8060U"
...

Ese es el nombre de la tableta que se va a usar en los siguientes pasos.

Quien controlará la tableta para poder dibujar y hacer cosas será el servidor gráfico X.org, por lo tanto se edita el archivo de configuración de X.org:

sudo gedit /etc/X11/xorg.conf

En mi caso tuve que comentar, dentro del archivo xorg.com, la sección del ratón (mouse), porque hay que agregar una nueva. También agregué lo que indica en el manual de configuración del driver ‘wizardpen’. En definitiva esto fue lo que comenté y lo que agregué:

#Section "InputDevice"
#       Identifier      "Configured Mouse"
#       Driver          "mouse"           
#EndSection

Section "InputDevice"
Identifier      "Configured Mouse"
Driver          "vmmouse"         
Option          "Emulate3Buttons"       "true"
EndSection                                    

Section "InputDevice"
Identifier      "WizardPen Tablet"
# Paste the name of the tablet as found in the previous step
Option          "Name"          "UC-LOGIC Tablet WP8060U"   
Option          "SendCoreEvents"        "true"
Driver          "wizardpen"
Option      "TopX"      "5619"
Option      "TopY"      "6554"
Option      "BottomX"   "29405"
Option      "BottomY"   "29671"
Option      "MaxX"      "29405"
Option      "MaxY"      "29671"
EndSection

Y al final agregué esto último:

Section "ServerLayout"
Identifier      "Default Layout"
Screen          "Default Screen"
InputDevice     "WizardPen Tablet" "SendCoreEvents"
InputDevice     "Configured Mouse" "CorePointer"
EndSection

Lo demás lo dejé igualito.

Reiniciar X y listo, o casi
Hay que reiniciar las X para que tome los cambios, como se indica en el instructivo de instalación. En mi caso el sistema se clavó completamente (ni las terminales virtuales que salen con Ctrl+Alt+Fn funcionaron más). Así que me tocó reiniciar después de varias semanas de tener la computadora ‘encendida’ (uptime), si no tomamos en cuenta el hecho que siempre la pongo a hibernar (se apaga) jajaja.

Al reiniciar la tableta ya funcionaba. No la he calibrado hasta ahora porque me gusta como está funcionando. Si hago la calibración, lo publicaré por aquí.

En Inkscape
Para que funcione en Inkscape hay que irse hasta el menú ‘Archivo->Dispositivo de entrada’, elegir ‘WizarPen Tablet’ y poner el modo ‘Pantalla’ o ‘Ventana’ para que funcione la presión del lápiz, dale ‘Guardar’ para que tenga efecto siempre.

En GIMP
En GIMP hay que ir al menú ‘Editar->Preferencias’ luego seleccionar en la lista izquierda ‘Dispositivos de Entrada’, de allí seleccionar ‘Configurar los dispositivos de entrada extendidos’, elegir igual ‘WizarPen Tablet’ y poner el modo ‘Pantalla’ o ‘Ventana’ para que funcione la presión del lápiz, dale ‘Guardar’, cerrar la ventanita en luego seleccionar el botón ‘Guardar la configuración del dispositivo de entrada ahora’ para que todo quede guardado y funcione siempre.

Suerte si tienes una de estas o quieres comprar una. El dibujo de la tabla digital arriba es hecho con la tabla funcionando.

Próximo evento: Jornadas de Software Libre en Cúcuta

Amigos del grupo de usuarios de Ubuntu Colombia han hecho una invitación a los Ubunteros Venezolanos para que participen en las Jornadas de Software Libre a realizarse en la ciudad de Cúcuta.

Según la propia página de las jornadas: “Las Jornadas de Software Libre 2009 se realizaran en La Ciudad Frontera, Cúcuta – Norte de Santander, de 30 de Octubre al 1 de Noviembre en las instalaciones de la Universidad Francisco de Paula Santander y el Hotel Bolivar. Es un evento totalmente libre.”

Entonces cualquiera puede ir, no solamente miembros de Ubuntu Venezuela, así aprenden un poco sobre el SL en Colombia y también de las charlas y ponencias. Si te queda cerca, no te lo pierdas. Lástima que a mi me queda lejos…

Comienza el Ubuntazo

Aún no ha llegado la gente, pero ya tenemos casi todo listo para comenzar. Esperamos que lleguen bastantes para las charlas. Hay CDs quemados con Ubuntu y KUbuntu gracias a que la vez pasada Danilo trajo un paquete de discos en blanco que para esta vez se grabaron.

Aún no se ha logrado la conexión con NetLynx, pero allí vamos, poco a poco.

Una relación entre la POO y las oraciones.

Una relación entre las oraciones, las clases, las variables y los métodos.

He estado viendo algún código escrito en Java que resulta no solo un poco difícil de entender sino que también es muy pesado para leer. Es un código difícil de entender porque el algoritmo no se ve claramente, resulta que muchas veces el programa tiene 300 o 500 líneas de código contínuas con puros detalles de implementación, todo metido en un solo método. En la mayoría de los casos, ese código hace algo sencillo como: generar un archivo con un formato particular, aplicar unas reglas a unos registros de BD, generar un reporte y cosas así. Pero resulta muy dificil de entender por la estructura desorganizada del código. También resulta pesado de leer precisamente por ese desorden, porque el código está todo metido en un solo método de Java con todos los detalles de implementación uno tras otro.

Ese código resulta difícil de mantener: toma mucho tiempo entender lo que hace. Al leerlo hay que adivinar el algoritmo y a la vez estar pendiente de los detalles. Cuando se llega a la mitad de un método que tiene 400 líneas de código, ya uno no recuerda lo que hacen las primeras líneas. En ese momento uno desearía que el código estuviera dividido en subtareas y que las subtareas sean llamadas de forma ordenada en un método controlador que sea corto y que al leerlo se vea claramente el algoritmo.

A raíz de esto me puse a reflexionar varias cosas sobre la programación orientada a objetos y sobre el diseño de los programas. Alguna gente piensa que mientras se programa también se va diseñando la solución. Esto no significa que no se haga un diseño previo de los programas, lo que significa es que la programación implica un esfuerzo intelectual que incluye la generación de parte del diseño del programa, más que todo el diseño detallado. Esto ocurre frecuentemente porque es muy costoso y lleva mucho tiempo hacer un diseño detallado para luego programarlo de forma casi mecánica; por el contrario en muchos casos es más conveniente hacer un diseño hasta cierto nivel de detalle intermedio y saltar luego a la programación, donde se teminan de diseñar los detalles mientras se construye el programa.

Es probable que en los programas que yo vi no pasaran por ninguna etapa de diseño. En algunos casos da la impresión que ni siquiera se reflexionó un poco sobre la estructura del programa. Ni hablar siquiera de refactoring; es comprensible que un primer diseño y un primer programa tenga ciertos defectos, al hacer refactor se logra ir mejorando el diseño del programa y la estructura del código fuente. Pero en estos casos hay indicios de que no se intentó hacer refactoring, da la impresión que dejaron el primer código que hicieron y funcionó, sin preocuparse por la estructura.

La Reflexión
Hay muchas cosas que se pueden hacer para remediar este problema, basta con seguir los consejos de programación que existen desde hace años.

Pero esto me ha llevado a una sencilla reflexión de cómo enseñar algunas cosas a las personas que están aprendiendo a programar y también a los que programan desordenadamente. El bojetivo de esta reflexión es buscar una forma sencilla de explicar o enseñar a los programadores un solo aspecto sobre el paradigma de programación orientado a objetos. Aquí van mis reflexiones.

La Oración: Sujeto y Predicado
La oración está compuesta principalmente por dos elementos: sujeto y predicado.

El sujeto de la oración es la persona, ser o cosa sobre la cual se está refieriendo.

El predicado es lo que hace o sobre lo que se aplica en el sujeto. Existen dos tipos de predicados: predicados nominales y predicados verbales.

Los predicados nominales representan una cualidad o un estado del sujeto en la oración. Los predicados verbales representan una acción del o sobre el sujeto.

Ejemplos de Oraciones
Veamos ahora con unos ejemplos:

Oración: el ratón está quieto
El sujeto es: el ratón; el predicado es de tipo nominal, ya que representa una cualidad o estado del ratón: está quieto.

Oración: el ratón se detiene
El sujeto sigue siendo: el ratón; el predicado ahora es de tipo verbal, pues representa una acción que está realizando el sujeto: se detiene. La diferencia con el predicado nominal del ejemplo anterior es que no se sabe si el ratón está quieto o no, solo se sabe que está detiéndose.

Oración: el ratón salta de la ventana al jardín
Esta oración es más complicada, el sujeto sigue siendo el mismo ratón; el predicado es verbal, porque indica una acción que está haciendo el ratón, pero da unos datos adicionales que son la ventana y el jardín, los lugares de origen y destino del salto. La ventana y el jardín forman parte nominal del predicado porque indican el estado anterior y el estado posterior a la acción (es decir al salto).

¿Qué tiene que ver esto con la POO?
Ya entendiendo esta simple estructura de la oración pasamos a ver cómo se une con la programación orientada a objetos.

Clases ~ Sujetos
En muchos lenguajes el programador va construyendo clases para modelar el programa que quiere construir.

Supongamos que queremos hacer un programa para controlar los ratones virtuales dentro de un juego de simulación que pasea por las casas de las personas virtuales. Entonces podríamos tener una clase llamada Ratón ya que todos los ratones harán básicamente lo mismo: merodear por allí.

public class Raton

Es algo muy natural que el sujeto de la oración se convierta en el objeto o la clase al momento de programar. En la mayoría de los casos los objetos y las clases representan sujetos de las oraciones.

Supongamos que queremos hacer unos reportes de personas asociadas a una logia que llevan: encabezado, cuerpo y un total, cada uno de una base de datos distinta. Al momento de analizar la información de lo que va a hacer el reporte nos damos cuenta que:
– Cada reporte debe colocar las etiquetas nombre, teléfono y servicio en el encabezado.
– Cada reporte debe buscar los datos en una base de datos.
– Cada reporte debe escribir correctamente el nombre, el teléfono y el servicio correcto para cada asociado.
– Cada reporte debe escribir un pie con el total de los asociados.

Vemos que son oraciones, cada requerimiento analizado se puede describir con una oración. En este caso el sujeto siempre es “el reporte” y que todos los reporte hacen básicamente lo mismo, por lo que se podría tener una clase “Reporte” que modele este sujeto:

public class Reporte

Ahora bien, ya vimos que los sujetos en las oraciones se modelan como clases y objetos en la POO. ¿Qué pasa con los predicados? pues bien, veamos cada tipo de predicado por separado.

Predicados Nominales ~ Variables o Atributos de Clases y Objetos
Para el caso de los predicados nominales, estos son los que indican cualidad o estado del sujeto, se utilizan variables de objeto o atributos de objeto (en Java se llaman atributos). Ejemplo, para saber si el ratón está detenido y para saber su velocidad cuando se mueve o salta:

public class Raton {
boolean estaDetenido;
int velocidad;
}

Otro ejemplo con respecto a los reportes que vimos anteriormente, cada reporte toma sus datos de una base de datos distinta:

public class Reporte {
DataSource baseDeDatosDeAsociados;
}

Entonces vemos que los predicados nominales se modelan como atributos o variables de objeto o de clase.

Predicados Verbales ~ Rutínas, Funciones o Métodos
Finalmente los predicados verbales implican alguna acción (algún verbo que indica la acción) que realiza el objeto y se modelan como métodos porque es allí donde van los pasos necesarios para ejecutar una acción. Generalmente el objeto tiene un estado antes de ejecutar la acción y otro distinto luego que termina la acción. Ejemplos:

public class Raton {
boolean estaDetenido;
int velocidad;
String posicion = “ventana”;

boolean detener() {
estaDetenido = true;
velocidad = 0;
return estaDetenido;
}

void saltar(String desde, String hasta) {
if (posicion.equals(desde)) {
posicion = hasta;
}
}

void main() {
detener()
saltar(“ventana”, “jardin”);
}
}

public class Reporte {
DataSource baseDeDatosDeAsociados;

void main() {
baseDeDatosDeAsociados = …;
escribirEncabezado();
traerDatos();
escribirCuerpo();
escribirTotal();
}
void escribirEncabezado() {
….
}
void traerDatos() {
….
}
void escribirCuerpo() {
….
}
void escribirTotal() {
….
}
}

En el ejemplo sencillo que se da del Reporte se puede ver claramente el algoritmo de funcionamiento en el método main(). Lo importante aquí no es mostrar que el programa esté correcto o no, solo es mostrar un ejemplo sencillo de cómo organizar el código para que sea fácil de leer. Por eso busqué la relación que existe entre las oraciones que usamos para comunicarnos en nuestro lenguaje natural y la forma de modelarlas en la programación orientada a objetos y particularmente en Java. Elegí Java porque es el lenguaje en que esta escrito el código que leí.

Conclusiones y Poner Claramente El Algoritmo
Entonces:
– Sujeto: se modela como clases y objetos.
– Predicado nominal: se modela como atributos o variables de clases y objetos.
– Predicado verbal: se modela como métodos de clases y objetos.

No son reglas dogmáticas aunque pienso que aplican en la mayoría de los casos.

Adicionalmente noté que es mejor tener un algoritmo claro (como el método main() del ejemplo del Reporte) y delegar los detalles en subrutinas (métodos de Java). Mientras los nombres de los métodos sean representativos de la acción que realmente hace el método y cada método haga solo una cosa, el algoritmo se entenderá bastante fácilmente.

Terminó el primer Ubuntazo…

Hoy me tocó hacer 3 artículos del Ubuntazo. Y es que lo hicimos tan bien que hasta tuvimos tiempo de escribir.

Fue mucha gente. Se copiaron muchos ISOs tanto en CDs como en USB Drives. Algunos Pen Drives son muy lentos, pero la ventaja sobre el CD es que se puede grabar sobre varios Pen Drives al mismo tiempo.

Sala de charlas
Sala de charlas

Las charlas fueron muy buenas y la gente se fue contenta. Solo se instalaron 2 computadoras nuevas y se hicieron algunas cositas de soporte.

cantando
cantando

Al final cantamos una canción de software libre.