SocketChat Programmierung

BrownWolf

Grünschnabel
Hallo,

ich bin gerade dabei einen Socket Chat in Perl zu programmieren.
Leider kenne ich mich mit dem HTTP Protokoll nicht so richtig aus und ich hoffe das ihr mir helfen könnt.
Mein Problem ist, wenn man Daten per POST absendet, dann kommt erst nach mehreren Submits der Query String mit den Text Informationen. Hier mal der Code damit ihr euch ein Bild machen könnt. Wie hättet ihrs gemacht ? :

Code:
use IO::Socket;
use IO::Select;

my $socket = IO::Socket::INET->new(
LocalHost => '127.0.0.1',
LocalPort => 2020,
Proto => 'tcp',
Listen => 5,
Reuse => 1
) or die "Konnte Socket nicht erstellen: $!\n";

my $select = IO::Select->new($socket);
while(@ready = $select->can_read){
foreach $client(@ready){
if($client==$socket){
my $process = $socket->accept;
$select->add($process);
print $process "HTTP/1.1 200 OK\n\r";
print $process "Content-type: text/html\n\n";
sysread($process, $buffer, 4096);
$INFO{'QUERY_STRING'} = $1 if($buffer =~ m/\/\?(.+) HTTP/);
$INFO{'ACCEPT'} = $1 if($buffer =~ m/Accept: (.+)\*\/\*/);
$INFO{'ACCEPT_LANG'} = $1 if($buffer =~ m/Accept-Language: (.+)\s/);
$INFO{'USER_AGENT'} = $1 if($buffer =~ m/User-Agent: (.+)\s/);
$INFO{'HOST'} = $1 if($buffer =~ m/Host: (.+)\s/);
$INFO{'CONNECTION'} = $1 if($buffer =~ m/Connection: (.+)/);
$INFO{'PROCESS_HOST'} = $process->peerhost;
$INFO{'PROCESS_PORT'} = $process->peerport;
$INFO{'CHATTER'} = $select->count;
--$INFO{'CHATTER'};
foreach $info(split /&/, $INFO{'QUERY_STRING'}){
($key,$value) = split /=/, $info;
$key =~ tr/+/ /;
$value =~ tr/+/ /;
$key =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ge;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ge;
$FORM{$key}=$value;
}
open(DAT,"./Online/$FORM{sid}.dat");
@read = <DAT>;
close(DAT);
chomp $read[0];
$nick = $read[0];
for($i=0;$i<30;$i++){ print $process "<!-- BUFFER //-->\n"; }
if($FORM{action} eq "messages"){
select($process);
print<<"EOT";
<head>
<script language="JavaScript">
function scroller() {
window.scrollBy(0,50);
setTimeout("scroller()",20);
}
scroller();
</script>
</head>
<body bgcolor="#222222" text="#FFFFFF"><font face="Tahoma" size="2">
Willkommen im Chat, <b>$nick</b>.<br>
Du befindest dich im Raum <i>{ROOM}</i>.<br>
Es befinden sich momentan $INFO{'CHATTER'} Chatter im Chat.<br><br><br>
</font>
</body>
EOT
select(STDOUT);
}elsif($FORM{action} eq "input"){
select($process);
print<<"EOT";
<html>
<head>
</head>
<body bgcolor="#000000" text="#FFFFFF">
<form action="http://127.0.0.1:2020" method="POST" target="b_dummy">
<input type="hidden" name="action" value="input">
<b><font face="Tahoma"><small>$nick:</small></font></b> <input type="text" name="text" size="50" maxlength="250"> <input type="submit" name="submit" value="Senden">
</form>
</body>
</html>
EOT
foreach $candidates($select->can_write){
if($candidates ne $process){
print $candidates $buffer;
}}
select(STDOUT);
$select->remove($process);
$process->close;
} elsif($FORM{action} eq "options"){
select($process);
print<<"EOT";
<body bgcolor="#000000" text="#FFFFFF">
EOT
select(STDOUT);
$select->remove($process);
$process->close;
} else {
select($process);
print<<"EOT";
<body bgcolor="#222222" text="#FFFFFF">
<center><font face="Verdana"><H1>Unbekannte Methode</H1></font><br>
<br>Die Methode "$FORM{action}" ist dem Chat nicht bekannt.</center>
EOT
select(STDOUT);
$select->remove($process);
$process->close;
}} else {
$select->remove($client);
$client->close;
}}}

Sorry das der Code so lang war :rolleyes:
Wer mir Ratschläge in Socketchat Programmierung geben will bzw. mich unterstützt der kann eine Mail an Sascha2481@gmx.net schreiben. Freue mich riesig wenn ich Emails bekomm :)

BrownWolf
 
Wenn du per Perl Daten die per POST übermittelt werden abfangen willst, musst du die aus der Umgebungsvariable CONTENT_LENGTH lesen:

Code:
read(STDIN, $input, $ENV{'CONTENT_LENGTH'});

	@pairs = split(/&/, $input);
	foreach $pair (@pairs) {
	($name, $value) = split(/=/, $pair);
	
	$name =~ tr/+/ /;
	$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
	$value =~ tr/+/ /;
	$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

	$FORM{$name} = $value;
	}

Diese Konstrukt holt die Daten aus $ENV{'CONTENT_LENGTH'}, splitet sie entsprechend in Schlüssel => Wert Paare, übersetzt dann hexadezimal Zeichen in Ascii Zeichen und packt anschliesend jedes Schlüssel => Wert Paar in den Hash %FORM.

Besser wäre allerdings, wenn du für sowas das Modul CGI verwendest, das geht dann so:

Code:
use CGI;

my $q = new CGI;

my %INPUT = $q->Vars;

So werden automatisch die übermittelten Daten (Ob nun GET oder POST, allerdings nur eines von beiden, wenn über beide wege Daten kommen hat eines von beiden Priorität, ich weis allerdings nicht welches!) in den Hash %INPUT als Schlüssel => Wert Paare hinterlegt, ausserdem ist diese Methode ausgefeilter und ist die empfohlene Variante für sowas.

Wenn du dich Allgemein für solche Dinge wie Socketprogrammierung interessierts, dann kannst du dir ja mal die POE Klasse ansehen, welche extra für solche Aufgaben entwickelt ist und auch bereits einen fertigen HTTP-Server bereitstellt, über den du dann deine WebSiten HTTP-Konform an den Browser versenden kannst.
 
Hallo,

danke für deine Antwort.
Das Problem ist, das wenn man das IO::Socket Modul benutzt man seinen eigenen Webserver(?) erstellt.
Dadurch sind alle Einträge in %ENV nicht mehr vorhanden.
Und auch <STDIN> kann bei POST nicht ausgelesen werden.
Ich weiss einfach nicht mehr weiter.

Gruß BrownWolf
 
hallo.

Wollt mal fragen, ob mir jemand ein gutes tut sagen kann, bei dem erklärt wird wie man seinen eigenen perl/cgi chat schreibt. Wenn es das gibt bitte in deutsch! :)
 

Neue Beiträge

Zurück