2012-10-31 4 views
1

Je tente d'émuler un serveur TCP sur le même ordinateur sur lequel l'application est en cours d'exécution. Je ne sais pas si cela peut être fait en Perl parce que je ne suis pas très expérimenté. Avec le code ci-dessous, la première réponse fonctionne mais je ne sais pas comment implémenter la seconde.Serveur TCP multiple recevoir et répondre

#!/usr/bin/perl -w 

use IO::Socket::INET; 
use strict; 


my $socket = IO::Socket::INET->new('LocalPort' => '3000', 
        'Proto' => 'tcp', 
        'Listen' => SOMAXCONN) 
    or die "Can't create socket ($!)\n"; 
print "Server listening\n"; 
while (my $client = $socket->accept) { 
    my $name = gethostbyaddr($client->peeraddr, AF_INET); 
    my $port = $client->peerport; 
    while (<$client>) { 
    print "$_"; 
    print $client "RESPONSE1"; 
    } 
    close $client 
    or die "Can't close ($!)\n"; 
} 
die "Can't accept socket ($!)\n"; 

EDIT: Merci les gars pour l'imput, je me suis retrouvé avec php fait et son travail, yay!

+0

vous devez 'fork '. Voir cette question par exemple http://stackoverflow.com/questions/7662711/perl-forked-socket-server-stops-accepting-connections-when-a-client-disconnects –

+0

soit 'fork' ou utilise un événement piloté io, par ex. [Programmation événementielle en Perl en utilisant le module Event] (http://cpansearch.perl.org/src/JPRIT/Event-1.20/Tutorial.pdf) – ErikR

+0

Même l'auteur de Event ne le recommande plus, essayez AnyEvent, POE, IO :: Async, ou pour une API similaire à Event, essayez EV – MkV

Répondre

2

Utilisez Net::Server pour la connexion, et une variable dans le sous pour conserver l'état actuel (état $ dans ce code); quelque chose comme ceci:

package MyServer; 
use base qw/Net::Server/; 
use strict; 
use warnings; 

sub process_request { 
    my $self = shift; 
    my $state = 0; 
    while (<STDIN>) { 
    s/\r?\n$//; # like chomp but for crlf too 
    if ($state == 0 and $_ eq 'data1') { 
     print "> okay1\n"; 
     $state++; 
    } elsif ($state == 1 and $_ eq 'data2') { 
     print "> okay2\n"; 
     $state++; 
    } else { 
     last if $state == 2; 
     $state = 0; 
    } 
    } 
} 

my $port = shift || 3000; 
MyServer->run(port => $port); 

L'exemple dans le Net :: serveur POD à l'aide d'une alarme suggère de délai d'attente des connexions, ce qui pourrait être appropriée ici. Le code ci-dessus fait ce qui suit:

$ nc localhost 3000 
data1 
> okay1 
data2 
> okay2 
data3 
$ 

Et si vous avez besoin de passer à un fork/preforking/non-blocage/co-routine système piloté, il y a une personnalité Net :: Server pour cela.

+0

Merci beaucoup pour votre réponse, puis-je définir dans l'état de données if1 et data2 hexadécimal comme ce eq '\ x {de} \ x {c0} \ x {ad}', le serveur ne semble pas répondre quand il correspond aux données – Mark

+0

Oui, unles qui se termine par une sorte de saut de ligne, cela ne fonctionnera pas, tandis que () lit des lignes, vous voulez faire quelque chose comme while (lire (* STDIN, local $ _ , 3)) au lieu de while () – MkV

+0

Si vous utilisez vraiment des guillemets simples pour la chaîne, vous devez utiliser des guillemets doubles pour que l'échappement hexadécimal fonctionne, c'est-à-dire $ _ eq "\ x {de} \ x {co} \ x {ad} " – MkV

0

"prêt à aller" code:

package MyServer; 
use base qw/Net::Server/; 
use strict; 
use warnings; 

sub process_request { 
    my $self = shift; 
    my $state = 0; 
    $| = 1; 
    binmode *STDIN; 
    while (read(*STDIN, local $_, 3)) { 
    if ($state == 0 and $_ eq "\x{de}\x{c0}\x{ad}") { 
     print "\x{c4}\x{1a}\x{20}\x{de}"; 
     $state++; 
    } elsif ($state == 1 and $_ eq "\x{18}\x{c0}\x{0a}") { 
     print "\x{11}\x{01}\x{73}\x{93}"; 
     $state++; 
     last; 
    } 
    } 
} 

my $port = shift || 3000; 
MyServer->run(port => $port); 
0

Il me semble process_request sous ne fonctionne pas correctement lorsqu'un port bas est réglé (dans ma situation, port 23). En particulier, avec un port bas, lors de l'analyse de l'entrée de données, la première requête contient des caractères supplémentaires (mais tout va bien avec les requêtes suivantes). Avez-vous un pourboire? Merci