PDA

Visualizza la versione completa : [STDOUT] Pipe con socket? Siete bravi?


LordSaga640
01-03-2005, 17:47
Ciao, so che questo post dovrei metterlo nella sezione PERL e CGI, però il mio problema, come farò capire, è più di tipo...insomma, interazione con pipe che sono in generale nella programmazione, vabbè....passiamo ai fatti, cioè, al codice.

Il mio problema riguarda l'esecuzione di alcuni programmi in un mio software.
Cioè, ho fatto un webserver che esegue CGI.
Ho scritto due funzioni per eseguire CGI e spedirli al browser.

La prima funzione è questa:


#$exe è il programma da eseguire. es: C:/php/php.exe
# $getp i parametri da passare per argv
# $postd i parametri arrivati con il metodo POST da inviare all'STDIN
sub xopen {
my ($exe,$getp,$postd)=@_;
$getp="" unless defined $getp;
my ($writer, $reader,$pagina,$vecchioin); # Dichiaro le variabili
pipe($reader,$writer); # Creo una coppia di pipe per inviare i dati al processo tramite STDIN
$writer->autoflush(1); # Svuoto il canale
open $vecchioin, "<&", \*STDIN or return undef; # Mi salvo il ref del vecchio STDIN
open (STDIN, "<&",$reader) or return undef; # Sovrascrivo il ref di STDIN con la pipe
open (PROG, "$exe $getp |") or return undef; # Avvio il processo aprendo una pipe in lettura
close $reader; # Chiudo la pipe destinata all'altro processo.
print $writer $postd if defined $postd; # Invio i dati tramite la pipe all'altro processo
$pagina.=$_ while <PROG>; # Salvo in uno scalare il testo che l'altro processo produce su STDOUT
close PROG; # Il processo dovrebbe essere già chiuso a questo punto ma di prassi...
close $writer; # Chiudo la pipe, anche se funzionava quando la lasciavo aperto
open STDIN, "<&",$vecchioin or die "impossibile aprire STDIN $!\n" if $vecchioin; # Reimposto il vecchio STDIN :)
# Tutto è nuovamente come prima e torno quello che il processo ha prodotto :)
return $pagina;
}

La funzione cattura STDOUT stampato ad esempio dal file php.exe che esegue uno script.
Questa funzione va benissimo e riesco a vedere tutte le pagine senza grossi problemi. Il problema è però che il mio programma si blocca fino a che lo script php non è concluso.


QUindi ho pensato di aprire l'STDOUT e L'STDERR sullo socket in modo che eseguo il programma e penso alle altre richieste, così php.exe deve pensare lui ad inviare sullo socket.


# $sock è l'oggetto socket del client.
sub open_rep {
my ($exe, $getp, $postd, $sock)=@_;
$getp="" unless defined $getp;
my ($old_stderr, $old_stdout);
open $old_stdout, "<&", \*STDOUT or return undef;
open $old_stderr, "<&", \*STDERR or return undef;
open STDOUT, ">&", $sock or return undef;
open STDERR, ">&", $sock or return undef;
open (PROG, "| $exe $getp") or return undef;
print PROG $postd if defined $postd;
PROG->autoflush(1);
open STDERR, ">&",$old_stderr or die "impossibile aprire STDERR $!\n"; # Reimposto il vecchio STDIN :)
open STDOUT, ">&",$old_stdout or die "impossibile aprire STOUT $!\n"; # Reimposto il vecchio STDIN :)
return 1;
}

La funzione non fa altro che mettere STDOUT sullo socket. POi esegue php.exe, reimpostare i vecchi STDOUT e STDERR e uscire dalla funzione.

Il primo modo funziona.

Il secondo mi da dei problemi con explorer ma funziona se uso telnet.
Come faccio a capire perchè explorer non mi fa vedere la pagina anche se con telnet riesco a vederla perfettamente?

Grazie in anticipo.

LordSaga640
01-03-2005, 22:40
Da quel che ho capito il problema sta negli Header °_°
Però c'è un problema strano che non sono riuscito a capire neanche leggendo l'RFC del protocollo HTTP/1.1.
In pratica riesco a vedere la pagina solo se il server (non lo script) inserisce un Content-Length.
La cosa è alquanto strana.

E' strana perchè se il Content-Length lo inserisco nello script non va. L'output generato è lo stesso però per una qualche ragione non si vede. Forse perchè i due pacchetti sono spezzati.

Anche gli script generano header.
Ho notato infati che apache, prima di legare l'STDOUT allo socket, aspetta di avere la parte completa di header. Quando poi ha tutti gli header generati dallo script allora invia gli header e collega l'STDOUT all'oggetto socket.
Io però non riesco a fare come fa apache. Cioè, catturare gli header e legare STDOUT allo socket dopo l'esecuzione di php.exe

Mi sembra strano che ci voglia un Content-Length per far vedere le pagine.
Mistero della fede.
Sapete mica aiutarmi? plzzz

Loading