Blogia
Geeks i d'altres

Més server web ..

Els darrers dies he afegit un bon grapat de millores al server. Primer de tot, la concurrència, que és un tema molt important. Pel meu compte vaig programar un server que es posava a escoltar al port 80, acceptava un HTTP Request i responia amb un HTTP Response, i s'acabava. Després vaig fer un bucle infinit, per que pogues acceptar infinites peticions.

Jo estava tot content, perque tenia un server que pensava que podria funcionar bé. Pero fa uns dies vaig xerrar amb un company que em va demanar si emprava concurrència. Com que jo no tenia ni idea de a que es referia, li vaig demanar que volia dir, i ell em va explicar molt bé el tema amb una analogia. En aquells moments, el meu server era com una cua de supermercat. Entrava una petició i es tornava la resposta, pero mentres no es podia acceptar cap altre petició, així que els altres clients havien d'esperar a que el que havia entrar primer fos contestat. A els que estodiau informàtica a la UIB en Ricardo Galli vos ho deu explicar molt millor a l'assignatura de sistemes operatius, ja que el meu server en aquell moment es pareixia molt a un sheduler implementant l'algoritme FIFO (first in first out, el primer que arriba es el que primer s'atèn, i no se n'atèn un altre fins que aquest no ha finalitzat).

Així que havia d'emprar concurrència per a fer el meu server més eficient. La idea es molt senzilla; poder atendre a més d'un client a l'hora. Pero un sol programa no pot fer dues coses a l'hora, així que aqui entren en joc els procesos fills. Als sistemes *nix, els procesos segueixen una jerarquia estricta, i un programa pot crear un procès fill amb la cridada fork() i asignar-li una tasca. Podeu trobar molta més informació a la ManPage de fork (si no trobau el fork al man, el més provable és que hagueu de baixar el paquet de Debian manpages-dev).
Vaig lletgir una mica sobre el tema, ja que el tenia molt verd (només ho recordava d'un llibre de sistemes operatius de Tannembaum que vaig començar a lletgir fa estona, pero vaig deixar a mitjes ..), pero va ser molt facil.

El que s'ha de fer és que el procès pare, el server, escolti al port 80. Quan arribi una petició per a servir una pàgina, s'ha de crear un procès fill que la serveixi, i tornar-se a posar a escoltar.

L'únic problema és que una vegada que el procès fill ha servit la pàgina, es queda en estat "zombie". L'única intenció d'aquest estat és que el procès pare pugi saber perque el seu fill ha "mort", pero com que nosaltres sabem que el 99,9% de les vegades que els fills moren és per que han acabat la seva feina, no ens interesa tenir cadàvers per casa (o ocupant un espai a la Taula de Procesos ;)), així que hem d'emprar waitpid() per a matar al fill ben mort i que no ens molesti. Al man de waitpid trobareu molta més informació, i no estaria gens malament que lletgisiu una mica de teoria sobre procesos (aquesta regla també se m'aplica a jo, perque estic bastant verd en el tema de estats dels procesos i coses així ... ja és hora de tornar a treure el llibre de Tannembaum de la biblioteca de l'Anselm Turmeda xD).

Bé, el tema está així, ara tenc un server web que fa feina amb procesos fills per servir les pagines (com feia l'Apache1), pero l'implementació del protocol HTTP és una vergonya. El meu objectiu actual és fer una cosa mitjanament estandart, creant uns bons HTTP Responses i acceptant alguna cosa més que rebre GETs i servir pagines en text/http :D

Com sempre, el codi está disponible en la seva darrera versió a "http://servomac.funpic.org/code/serverCon.c", sota la llicència GPL.

S'esperen comentaris, crítiques (tant constructives com destructives, no m'aconseguireu minar la moral) i tot el que sigi relacionat amb el tema del server. Salut!

2 comentarios

servomac -

¡Muchas gracias!
Me alegro de ver alguna opinión medianamente favorable ;)

Guti -

Te está quedando realmente bien.

Un saludo.