Vielen Dank für die Antwort.
Ich versuch einfach aus Spass an der Freude einen
Webserver zu schreiben. Ich habe auch bereits schon einen ziemlich weit gebracht, sprich mit Perl,PHP und sogar C-Script-Interface.
In diesem Webserver verwende ich select mit can_read(). Allerdings bin ich dann, als ich versucht habe Ihn in der Bandbreite zu begrenzen auf das geschilderte Problem gestossen.
Auch Versuche mit Fork oder Treads haben das Problem nicht gelöst.Damit eine sinnvolle Diskussionbasis entsteht
folgt ein Perl-Source, der das Problem aufzeigt.
#!/usr/bin/perl -w# TCP/HTTP-Server
# (c) 2009 Dieter Heinrich
use strict;
use warnings;
use Socket;
use IO::Socket::INET;
use IO::Select;
select(STDERR); $|=1; select(STDOUT); $|=1; # Autoflush
#=================================================================================
my $socket = IO::Socket::INET->new
( LocalPort=> 80,
LocalAddr=> "0.0.0.0",
Listen => 5,
ReuseAddr=> 1,
Proto => "tcp",
Type => SOCK_STREAM
);
#=================================================================================
my @fhn=(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); # Client-Handles
my @fhp=(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); # Lese-Zeiger auf $fhb[$i]
my @fhb=("","","","","","","","","","","","","","","",""); # Ausgabe-Puffer
my $sel = new IO::Select($socket); # Selectobjekt für diesen Socket erstellen
#=================================================================================
while(1)
{ my (@rdy,$buf);
@rdy=$sel->can_read(1); # Client-Anfragen ?, 1s blockierend
# Ausgabe im Sekundentakt häppchenweise (256Byte) senden
# eine Schleife mit $sel->can_write(0) ist offensichtlich nicht erforderlich
for (my $i=0; $i<=$#fhn; $i++) # offene Ausgabe-Anforderungen
{ if ($fhn[$i])
{ $fhp[$i]+=syswrite($fhn[$i],$fhb[$i],256,$fhp[$i]);
$fhn[$i]->flush; # Ausgabe flush (wahrscheinlich unnötig)
if ($fhp[$i]>=length($fhb[$i])) # alles ausgegeben ?
{ $sel->remove($fhn[$i]);
$fhn[$i]->close; # Verbindung schliessen
$fhn[$i]=0; # Verbindung = 0
}
}
}
# Client-Anfragen entgegennehmen
foreach my $fh (@rdy) # Client-Anfragen bearbeiten
{ my ($methode,$doc,$protokol)=("","","");
if ($fh==$socket)
{ $sel->add($socket->accept);
print "Client angenommen:";
} else
{ binmode($fh); $fh->autoflush(1);
RDL: while ($buf=<$fh>)
{ if ($buf=~/^(GET|POST)/) # Client-Anforderung ?
{ ($methode,$doc,$protokol)=split(/ /,$buf,3);
} elsif ($methode)
{ $buf =~s/[\x0a\x0d]+$//; # CR am Ende weg
if ($buf eq "") # Leer-Zeile ?
{ print $fh "HTTP/1.0 200 OK\n";
print $fh "Server: Test 1.0\n";
print $fh "Content-Type: text/html\n";
print $fh "Connection: close\n\n";
$doc =~ s/^\///g; # '/' am Anfang weg
# die Datei wird nicht sofort ausgeliefert, sondern in einen Ausgabe-Puffer
# geschrieben, der anschliessend zu Anfang der while-Schleife häppchen-weise
# im Sekunden-Intervall (can_read(1)) ausgegeben wird
my $i=0; # freien Ausgabe-Kanal suchen
while ($i<=$#fhn) { if (!$fhn[$i]) { last; } $i++; }
print $i."\n";
if ($i<=$#fhn)
{ $fhp[$i]=0; # Lese-Zeiger = 0
$fhb[$i]=""; # Ausgabe-Puffer leeren
$fhn[$i]=$fh; # Client-Handle, Ausgabe-Puffer gültig
open DOC,"<",$doc; # Ausgabe-Puffer füllen
while (<DOC>) { $fhb[$i].=$_; } close DOC;
}
last RDL;
}
}
}
#$sel->remove($fh); # hier würde die Client-Verbindung
#$fh->close; # normalerweise wieder geschlossen
}
}
}
# Verhalten:
# fordert ein Client ein Dokument an, wird dies häppchenweise im Sekundentakt ausgeliefert.
# Dabei wird der Kanal @fhn mit dem Index 0 genommen.
# fordert während dieser Ausgabe ein zweiter Client ein Dokument an, so wird dieser erst
# bedient, wenn der erste Client fertig bedient wurde. Für den zweiten Client wird wieder
# der Kanal @fhn mit dem Index 0 genommen.
1;
__END__
Gruss Dieter
Datum: 13.01.2009-19:28
