#!/usr/bin/perl -W # TP protocole HTTP # # Question 2 # # Antoine Miné # 20/04/2007 use Socket; # pour avoir l'équivalent Perl de socket.h use IO::Handle; # pour avoir autoflush $url = $ARGV[0] or die "utilisation: $0 URL"; # format d'une URL: protocole://serveur:port/page (cf. RFC 2396) # le port est optionnel # cette expression gère adresses textes et IPv4, mais pas IPv6 (cf. RFC 2732) ($protocole, $serveur, undef, $port, $page) = $url =~ /^([a-z]+):\/\/([a-z0-9.-]+)(:(\d*))?(\/.*)$/; # port 80 par défaut $port = 80 if ! defined $port; # vérification de l'URL die "URL mal formée $url" unless defined $protocole && defined $serveur && defined $port && defined $page; die "protocole $protocole inconnu" unless $protocole eq "http"; # détermination de l'adresse IP du serveur $ip_serveur = gethostbyname($serveur) || die "IP du serveur $serveur introuvable"; # transformation au format interne utilisable par connect $addr_sin = sockaddr_in($port, $ip_serveur); # création d'une socket TCP/IP socket(SOCKET, PF_INET, SOCK_STREAM, 0) || die "échec de socket: $!"; # le tampon de SOCKET sera vidé après chaque appel à print autoflush SOCKET 1; # connection au serveur connect(SOCKET, $addr_sin) || die "échec de connect: $!"; # envoie d'une requête HTTP (cf. RFC 2616) print SOCKET "GET $page HTTP/1.1\r\n"; print SOCKET "Host: $serveur:port\r\n"; print SOCKET "User-Agent: httpget\r\n"; print SOCKET "Connection: close\r\n"; print SOCKET "\r\n"; # lit et vérifie le statu de la réponse $statu = ; ($code, $texte) = $statu =~ /^HTTP\/[0-9.]+ (\d+) ([^\n\r]*)/; die "erreur $code $texte" unless $code == 200; # saute les en-têtes de la réponse while () { last if $_ eq "\r\n"; } # copie la page sur la sortie standard while () { print "$_"; }