Thursday, September 13, 2007

Lío de navegadores

Son algo curioso, los exámenes. Cuando estás estudiando, ves mil cosas en Internet que te interesan, se te ocurren otras mil que hacer en cuanto acabes y literalmente te faltan manos y ojos para todo lo que te gustaría hacer a la vez. Y sorprendentemente, en cuanto acaban, junto con todo lo que has estudiado, se te olvida también todo lo que querías hacer. Para los exámenes de febrero me haré una lista.

Bien, ahora al tema... más o menos. Ya que aún no me he presentado (¿lo haré algún día?) he de decir que hasta hace nada mi ordenador principal era un Sony Vaio SZ1XP con el XP original, con toda la mierda de fabrica desinstalada y para navegar usaba el Seamonkey.

Volviendo al tema de las cosas por hacer, yo he empezado por limpiar. Tenía el escritorio de mi XP hasta arriba de howtos, vídeos, apuntes, exámenes de años anteriores, links, ejemplos de código y demás fauna silvestre. Si estuvieran en mi escritorio real, esto es, en la mesa de mi cuarto, lo que yo y cualquiera haría sería tirarlo todo al cajón para obtener una limpieza fácil y rápida. A falta de cajones, la carpeta Mis Documentos bien me sirve para ello.
Un vez limpito todo, me puse a trastear por la web, a ver si me acordaba de algo y en mi página de inicio vi un feed interesante de slashdot. Lo expandí y me puse a leerlo y en mitad de la lectura despareció el texto y salió "La información no se encuentra disponible". Como no era la primera vez que pasaba decidí abandonar Google y buscar algo mejor. Como hace tiempo vi que un amigo usaba netvibes me registré y lo estuve probando. Una maravilla, muchísimo mejor que iGoogle. Y cómo no, la opción de personalizar no pasó desapercibida y los skins que tiene son otra maravilla. Pero claro, el bonito skin negro del netvibes no pegaba nada con el modern del mozilla. Sabía que skins para seamonkey hay poquitos, pero es que los pocos que había han dejado de funcionar con las nuevas versiones. Así que decepcionado y con tiempo libre ya tenía algo que hacer.
Como los navegadores maduros se pueden contar con los dedos de una mano (bueno, y media) no iba a ser muy complicado.
Primer candidato: Safari 3. Lo había probado en el curro unos días antes en el PC de un compañero. Súper bonito, pero aun en fase beta, un pelín inestable y por lo que vi en la web, sin posiblidad de skins.
Segundo candidato: Opera. Los recientes comentarios sobre la v9.5 alpha sonaban muy bien y tenía ganas de probarlo. Trasteando por la web vi que tenía posiblidad de skins y me baje la estable, v9.23, para probar. ¡Y qué navegador! Me ha dejado impresionado. Cientos de skins súper currados, widgets, pestañas avanzadas, cliente torrent integrado, gran gestor de descargas y cosas que aun no he probado como gestos de ratón. Lo mejor son las pestañas. Si algo me mantenía usando seamonkey en lugar de firefox eran las pestañas. Nada de Ctrl + T para abrir pestañas. Se teclea la url, Cntrl + Enter y voilá, nueva pestaña con la url. Nada de teclear las busquedas en la barra de Google de la derecha. Se teclean los términos donde siempre, flecha arriba, Enter (o Cntrl + Enter para pestaña nueva) y voilá, tenemos la búsqueda. En el opera es incluso mejor. Si ponemos "g cosa" busca "cosa" en Google. Con "y cosa" busca "cosa" en Yahoo. Con Shift + Enter lo abre en una pestaña nueva y con Ctrl + Shift + Enter, en una pestaña nueva en segundo plano. Im - presionante. Tan sencillo y tan, tan cómodo. Y lo mismo para los links. Pero tantas cosas buenas tienen su punto en contra. Justo cuanto iba a postear todas estas maravillas... blogger no funciona con opera. Vaya desilusión, resulta que opera tampoco es "el navegador definitivo". Mientras espero al Opera 9.5 seguiré usando Seamonkey para bloguear y Opera para navegar.
Me he quedado tan satisfecho con Opera que he dejado de buscar y he decidido no probar Netscape (si, sigue vivo) y alguno otro que quedaba por ahí. Y los dos mas populares: IE7 y Firefox ya estaban descartados por su gestión de pestañas y urls.

Ah, y ya de paso, con el Opera y el netvibes en negro, mis ventanas de XP originales y fondo de escritorio en azul no pegaban, así que también los cambié. Ya que estaba... Aquí os dejo unas capturas del resultado final del invento:

Escritorio:

Menú inicio:


Netvibes en Opera:

Bueno, ya está bien por hoy. Ya toca cerrar el viejo Seamonkey y navegar un poco con el flamante Opera antes de dormir.
Hasta la próxima!

PD: en el anterior post, el codigo está un poco mal. Donde pone ptr->s debería poner sólo s. Fallo mío al adaptar el código original. No lo edito porque blogger y el código en C se odian y sale deformado en la edición :(

Wednesday, September 12, 2007

Sockets para linux - cliente

A ver si esta vez ya me animo a ir actualizando el blog. El verano esta acabando, los exámenes están hechos, al fin tengo tiempo libre. Así que... ¿qué mejor para empezar que cumplir con lo prometido? Así que aquí va una de sockets de Berckley, por supuesto en C y en linux (GNU/Linux para los pedantes xD) La presentación... bueno, eso ya lo haré algún día.

El origen del código es una práctica para la asignatura de Sistemas Operativos Distribuidos, de la Facultad de Informática de la UPM. Pero esto es lo de menos, ya que el payload está, sólo interesa la parte de los sockets. Lo relevante es que viene de la implementación con sockets y sin estado. Esto afecta de manera que para cada comunicación se abre una nueva conexión y se cierra al terminar la petición. Algo al estilo HTTP 1.0. Bien, ¡manos a la obra!


Cuerpo del cliente
Este es el código útil que va a hacer cosas y entre ellas, enviar y recibir datos por la red. Sustituir ese código útil en los corchetes es tarea vuestra :P

RDIR *r_opendir(char *dirname) {
mensaje_t mensaje;
int s;
[...]
if ((ptr->s=conectar()) < 0) {
perror("error de conexion");
return NULL;
}
[...]
if ((aux=send(ptr->s, &mensaje, sizeof(mensaje), 0)) < 0)
perror("send mensaje");

if (recv(ptr->s, &mensaje, sizeof(mensaje), 0) < 0)
perror("recv mensaje");

close(s);
return [...];
}

Trivial, ¿verdad? Bueno, si sólo fuera eso sería estupendo, ya estaría todo claro, el código habla por sí mismo: conectar, enviar y recibir. De hecho también se podría usar read(...) y write(...) ya que s no es ni más ni menos que un descriptor de fichero. Pero se observa una sospechosa función conectar(), que como es de prever no viene en ninguna biblioteca y no hay direcciones, ni puertos ni nada de nada. Normalmente todo eso iría en el código principal, pero por hacerlo mas bonito y reusable lo separé en una función aparte, la cual no sería dificil de meter en un .h si fuera necesario.


Función conectar()
Esta es la que hace que el descriptor s contenga un socket listo para ser usado para hacer read y write sobre él, o si se prefiere, send(...) y recv(...).

int conectar(void){
struct sockaddr_in dir;
struct hostent *host_info;
int s;

if (getenv("SERVIDOR") == NULL || getenv("PUERTO") == NULL){
printf("Establecer SERVIDOR y PUERTO en variables de entrono\n");
return -1;
}

if ((s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("error creando socket");
return -1;
}
host_info=gethostbyname(getenv("SERVIDOR"));
memcpy(&dir.sin_addr.s_addr, host_info->h_addr, host_info->h_length);
dir.sin_port=htons(atoi(getenv("PUERTO")));
dir.sin_family=PF_INET;
if (connect(s, (struct sockaddr *)&dir, sizeof(dir)) < 0) {
perror("error en connect");
close(s);
return -1;
}
return s;
}

Lo primero se definen dos estructuras de datos para contener la informacion del socket a crear y del host destino.
En segundo lugar se comprueba (de manera chapucera) que las variables de entorno que indiquen el server y puerto están puestas. Se podrían usar valores fijos, pedirlos interactivamente, o lo que prefiramos.
Más tarde se crea el socket en sí, con una función sorprendentemente llamada socket(...). Lo creamos del tipo stream y protocolo TCP (sí, un poco de redundancia nunca viene mal, jeje...). Una vez tenemos el socket creado, necesitamos conectarlo y para ello necesitamos una direccion. Como lo que tenemos es un nombre (host.dominio.com) lo resolvemos con gethostbyname(...) y vamos construyendo la estructura que nos define el host destino. El siguiente campo se rellena con el puerto destino, que se ha de pasar a formato de red con htons(...) (por el tema de máquinas big-endian/little-endian). De hecho este nombre tan raro viene de "host to network, short"
Llegados a este punto tenemos el socket creado y una estructura que nos define exactamente dónde conectarlo. Pues una llamada a connect(...) y tenemos un socket listo para usar.

Resumen
El proceso en caso de no haber conexión, en el cliente es:
crear socket -> identificar host+puerto destino -> conectar socket -> enviar/recibir -> cerrar socket.

El caso del servidor lo dejamos para la siguiente entrada.