Sessió 5 curs programació linux
Sessió 5. 16-5-2008
Programació en xarxes
=====================
Mirar també la documentació sobre xarxes a la wiki del curs.
http://acacha.dyndns.org/mediawiki/index.php/Programació_en_xarxes
Per veure les connexions de xarxa: netstat
netstat --inet
compte! netstat -inet significaria netstat -i -n -e -t
quan un paràmetre és llarg, es fiquen dos guions
netstat --inet -n en comptes de noms de màquina, posa IP'S
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 1 0 147.83.75.145:39601 147.83.194.33:80 CLOSE_WAIT
en el protocol http, cada petició obre una connexió, la processa i la tanca. Passa per tots els estats. Cada petició té un timeout.
watch netstat --inet -> executa la comanda cada 2 segons (paràmetre que es pot canviar)- Aleshores navego per Internet i veig com va canviatn la informació.
watch serveix per qualsevol comanda. Per ex, watch ifconfig va mirant estadístiques de paquets rebuts i enviats (entre d'altres coses), i així veig el tràfic.
En comptes de watch també es pot fer netstat -c (mode continu, també es va executant contínuament)
$sudo netstat -puta | more -> ara surten més connexions. Concretament, els servidors en estat LISTEN estan escoltant peticions que els pugui arribar, com el MySQL. També ens diu el PID (id del procés)
tcp 0 0 localhost:mysql *:* LISTEN 2427/mysqld
amb aquesta informació podria matar el procés: kill 2427 -> mato el procés mysqld
per tornar a obrir: /etc/init.d/mysql start
SOCKET (endoll). Estem endollant dues màquines
A través d'un canal de comunicació (unix, tcp,...) envio informació a través del canal.
socket linux. Per exemple:
$ ls -la /var/run/mysqld/mysqld.sock
srwxrwxrwx 1 mysql mysql 0 2007-05-10 07:42 /var/run/mysqld/mysqld.socksi estableixo la connexió del mysql amb un socket linux, de fet va molt més ràpid.
Socket d'Internet.
protocol (tcp, udp, raw ip)
Berkeley sockets Application Programming
És una llibreria per desenvolupar aplicacions de xarxa amb C
man socket
socket() -> int socket(int domain, int type, int protocol);
per TCP i UDP el protocol és 0
socket a la wiki del curs: http://acacha.dyndns.org/mediawiki/index.php/Programació_en_xarxes#socket
bind() (lligar) -> hem de lligar el socket a una IP i a un port. De moment només tenim l'objecte socket (en terminologia POO). Ara falta fer alguna cosa amb ell.
Codi d'exemple.
INADDR_ANY -> són totes les IP de la màquina client (una màquina pot tenir varies interfícies)
sin.sin_port = htons(port); -> converteix el port a hexadecimal (la manera com ho entén el sistema, veure la wiki)
listen() -> sockets orientats a connexió (UDP no l'utilitza)
S'ha de diferenciar el listen d'acceptar connexions.
accept: amb el bucle while(1) estic esperant connexions (per exemple, en el cas d'Apache). Esperem connexions dels clients
és així com es programen els dimonis, per exemple el dimoni de l'Apache.
ps aux | grep apache -> un apache de fet té molts processos oberts
recv -> receive
send
treballen amb un buffer
Exemple client-servidor. Servidor d'echos.
Instal.lem Java + Eclipse + Subversion (seguir els passos de l'enllaç en la sessió 5)
modifiquem el client.c i li fiquem la IP del servidor. Compilem
aleshores:
./server -> el servidor es posa a l'espera
./client hola -> en el client es notifica, i en el servidor, que està a l'espera, també es notifica.
També es pot fer amb telnet:
em connecto al servidor de la companya:
$ telnet 147.83.75.144 8000 -> com que hi ha un procés, el servidor està escoltant. Escric, i em contesta el servidor.
nmap 147.83.75.144
sudo apt-get install nmap
-> fa un scanner de ports, i veig que el 8000 està obert
---
Faig telnet www.upc.edu 80
està a l'espera. escric index.html i em dóna la resposta
---
Canviem d'exemple: udp. Enviar missatges
Provem també el client i el servidor.
Experiència: mentre rebem els paquets, desconnectem físicament el cable de xarxa, i el tornet a connectar. Veurem que s'han perdut paquets, doncs el protocol udp és més ràpid, a costa de què no assegura la integritat de la informació (es perden paquets).
Ara ho fem funcionar pel port 6789
// set using SOCK_DGRAM for UDP:
if ((socket_descriptor = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Error obrint el socket\n");
exit(1);
}
./receive: /lib/tls/i686/cmov/libc.so.6: version `GLIBC_2.4' not found (required by ./receive) -> vol dir que li falta algun paquet per instal.lar:
sudo apt-get install libc6-dev
ln -al /lib/tls/i686/cmov/libc.so.6
No s'instal.la bé. com es soluciona?
make clean -> esborra els executables
make -> torno a generar els executables
Important!!
El procés de compilació en C
llegir a: http://atenea.upc.edu/moodle/mod/resource/view.php?id=288596
- include <stdio.h> -> on està stdio.h? està a /lib
find /lib -name include -print
whereis stdio
stdio: /usr/include/stdio.h /usr/share/man/man3/stdio.3.gz
Important! Si a Ubuntu no es troba stdio.h i les altres llibreries, és perquè no està instal.lat:
$ sudo apt-get install libc6-dev
i ho solucionem
if (iter >20) { -> canviem per un número més gros. Per ex, 50
fiquem en el receive.c la meva IP (147.83.75.145), i en el send.c la seva (147.83.75.144)
./receive -> es posa a escoltar
./send -> envia tota la iteració de paquets.
Per pantalla es veu:
Resposta del servidor:
paquet de dades amb l'identificador: 11 (de 1...50), que és el que m'ha enviat el send.c
Dimonis
======
programaciodimonislinux.pdf
Aplicació informàtica o procés que s'executa en segon pla.
echod.c
compilem i l'executem. S'hauria de veure en el monitor del sistema
(el codi de la solució no m'ha funcionat, l'altre sí)
ps aux | grep echod -> veig que s'executa, i també ho veig en el monitor
cursice 12852 0.0 0.0 1428 244 ? S 15:32 0:00 ./echod -> és aquest!
cursice 12923 0.0 0.1 2848 700 pts/1 R+ 15:34 0:00 grep echod
en el fitxer echod.c puc ficar sleep(10) (10 segons) abans del fork, i així controlar com es creen els fills (?. estudiar!)
per matar-lo, kill -9 12852
(o bé pidof echod)
En el monitor de processos, fico damunt(que sempre estigui en primer pla), veure tots els processos, i veure dependències (per veure quin és el pare i quin és el fill).
si surten caràcters extranys: reset.
per veure el pid del pare:
ps -elf