Perl - Remote Konsole steuern

Mirar

Mitglied
Hallo liebe Forumfreunde,

ich bin aktuell mit einem Projekt für die Schule beschäftigt und komme einfach nicht weiter.
Die Aufgabe ist, die Konsole eines anderen Rechners im gleichen Netzwerk zu steuern und die Ausgabe auf dem Client zu sehen. Dafür müssen wir Sockets nutzen.
Soweit funktioniert auch schon das meiste. Ich kann die Verbindung herstellen, einen Befehl wie z.B. "ipconfig" in der Client-Konsole eingeben und dieser wird dann auf dem Server/Remote-Rechner ausgeführt und die Ausgabe zurück zum Client geschickt.
Jetzt ist das Programm so geschrieben (Oder soll so geschrieben sein), dass man nachdem man einen Befehl eingegeben hat noch weitere Befehle eingeben kann. Halt als würde man tatsächlich die andere Konsole vor Augen haben. Allerdings wird nach dem ersten Befehl kein weiterer Befehl mehr ausgeführt. Eintippen ist ok. Ausführen nein. Könnte ihr mir da helfen?

Hier mein Code:

Server:
Perl:
#!/usr/bin/perl -w

use strict;
use IO::Socket;

print "Geben Sie den Port an...\n";
chomp(my $port = <STDIN>);

my $server = IO::Socket::INET->new(
    LocalPort    => $port,
    Type         => SOCK_STREAM, 
    ReuseAddr    => 1,           
    Listen       => 10 )         
    or die "Couldn't be a tcp server on port $port : $@\n";
	
print "Server started\n";

while(1) {
	while (my $client = $server->accept( ))
	{
		my $line = <$client>."\n";
		my $output = qx($line);
		print $client $output."\n";
	}
}

Und der Client:
Perl:
#!/usr/bin/perl -w

use strict;
use IO::Socket;

print "Geben Sie die IP des Servers an...\n";
chomp(my $ip = <STDIN>);

print "Geben Sie den Port an...\n";
chomp(my $port = <STDIN>);

my $socket = IO::Socket::INET->new(
    PeerAddr => $ip,  
    PeerPort => $port,  
    Proto    => "tcp",        
    Type     => SOCK_STREAM)  
    or die "Couldn't connect to $ip:$port : $@\nPlease check that the IP and the Port are correct!";

print "Connection was build\n";
print "Sie können nun die Befehle eingeben!\n";

my $command;

while(1) {
	
	$command = <STDIN>;
	print $socket $command;
	
	while(my $answer = <$socket>)
	{
		print $answer;  
	}
}

Danke im Voraus!

Gruß Mirar
 
Hallo,

irgendwie schaut deine Schleife im Server etwas merkwürdig aus: Der Server führt genau einen Befehl aus danach wartet er blockierend auf eine neue Clientverbindung, was ich nehme mal an (wenn ich mir den Client anschaue welcher nur genau ein connect) ausführt nicht so gewollt ist?

Zu deinem eigtl. Problem: Die Leseschleife im Client liest zeilenweise die Befehlsantwort vom Server und gibt diese zeilenweise auf der Console aus. Das Problem ist nur das das Lesen nicht abbricht wenn der Server nichts mehr schickt sondern blockierend solange gewartet wird bis wieder was geschickt wird. Da aber wenn die Befehlsantwort vom Server komplett gesendet wurde nichts mehr kommt blockiert dein Client und du kommst nie wieder zum Einlesen des neuen Befehls von STDIN. Du musst also vom Server ein EndOfCommand oder etwas ähnliches schicken damit du dem Client zu verstehen gibst das das Kommando jetzt zu Ende ist und ein neues eingegeben werden muss.

Probiers mal so:

Server:

Perl:
#!/usr/bin/perl -w

use strict;
use IO::Socket;

print "Geben Sie den Port an...\n";
chomp(my $port = <STDIN>);

my $server = IO::Socket::INET->new(
    LocalPort    => $port,
    Type         => SOCK_STREAM,
    ReuseAddr    => 1,
    Listen       => 10 )
    or die "Couldn't be a tcp server on port $port : $@\n";

print "Server started\n";

my $client = $server->accept( );

while(1) {
      my $line = <$client>."\n";
      my $output = qx($line);
      print $client $output."\nEOC\n";
}

Client:
Perl:
#!/usr/bin/perl -w

use strict;
use IO::Socket;

print "Geben Sie die IP des Servers an...\n";
chomp(my $ip = <STDIN>);

print "Geben Sie den Port an...\n";
chomp(my $port = <STDIN>);

print "$ip\n";
print "$port\n";
my $socket = IO::Socket::INET->new(
    PeerAddr => $ip,
    PeerPort => $port,
    Proto    => "tcp",
    Type     => SOCK_STREAM)
    or die "Couldn't connect to $ip:$port : $@\nPlease check that the IP and the Port are correct!";

print "Connection was build\n";
print "Sie können nun die Befehle eingeben!\n";

my $command;

while(1) {

    $command = <STDIN>;
    print $socket $command;

    while ((my $answer = <$socket>) ne "EOC\n")
    {
      print $answer;
    }
}

Gruß,
RedWing
 
P.S. Du könntest auch noch nach jedem Kommando den Stream explizit serverseitig schließen, auch dann würde die read-Funktion im Client zurückkehren, hier musst du nur etwas unschön einen neue Verbindung für jedes neue Kommando aufbauen:

Server:
Perl:
#!/usr/bin/perl -w

use strict;
use IO::Socket;

print "Geben Sie den Port an...\n";
chomp(my $port = <STDIN>);

my $server = IO::Socket::INET->new(
    LocalPort    => $port,
    Type         => SOCK_STREAM,
    ReuseAddr    => 1,
    Listen       => 10 )
    or die "Couldn't be a tcp server on port $port : $@\n";

print "Server started\n";


while(1) {
      my $client = $server->accept( );
      my $line = <$client>."\n";
      my $output = qx($line);
      print $client $output."\n";
      close $client
}

Client:
Perl:
#!/usr/bin/perl -w

use strict;
use IO::Socket;

print "Geben Sie die IP des Servers an...\n";
chomp(my $ip = <STDIN>);

print "Geben Sie den Port an...\n";
chomp(my $port = <STDIN>);

print "$ip\n";
print "$port\n";
while(1) {
   my $socket = IO::Socket::INET->new(
      PeerAddr => $ip,  
      PeerPort => $port,  
      Proto    => "tcp",        
      Type     => SOCK_STREAM)  
      or die "Couldn't connect to $ip:$port : $@\nPlease check that the IP and the Port are correct!";
    
    print "Connection was build\n";
    print "Sie können nun den Befehl eingeben!\n";
    
    my $command;


    $command = <STDIN>;
    print $socket $command;

    while ((my $answer = <$socket>))
    {
      print $answer;
    }

    print "Answer end\n";
}

Gruß,
RedWing
 
Guten Morgen,

ein dickes "Danke schön" von mir an dich RedWing!
Deine erste Lösung hat mir sehr weitergeholfen! Über die zweite Möglichkeit bin ich bereits einmal gestolpert jedoch fand auch ich das ziemlich unsauber weshalb ich das verworfen habe.
Jetzt kann ich auf jeden Fall erstmal weiterarbeiten :)

Danke
 
Zurück