Schrift
[thread]4463[/thread]

IO::Socket::INET - Kompletten Buffer einlesen

Leser: 5


<< >> 6 Einträge, 1 Seite
Gast Gast
 2007-04-27 18:07
#37518 #37518
Hi,

ich habe ein Problem mit dem Socket Buffering in PERL.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
my $socket = IO::Socket::INET->new(PeerAddr    => "127.0.0.1",
PeerPort => 41447,
Proto => "tcp",
Type => SOCK_STREAM,
Timeout => 300)
or die "$!\n";

print $socket "command1\n";
print $socket "command2\n";
print $socket "command3\n";


Ich connecte zu einem daemon und gebe diesem Befehle. Die Befehle geben eine oder mehrere Zeilen zurück (Strings). Nun möchte ich diese ganzen Zeilen in einem String zusammenfassen. Ist das möglich? Wenn ja wie? read() bietet mir die Möglichkeit die Antworten einzulesen. Aber setzt vorraus das ich die LÄNGE kenne...

Weiterhin muss ich wissen, ob es eine Möglichkeit gibt den Buffer (mit den Serverantworten) zu flushen.

bisher gebe ich die Zeilen mit getline() aus. Was aber nicht gewünscht ist, da ich auch mal nur die letzte Zeile im Buffer ausgeben will.

Ich hoffe ihr könnt mir weiterhelfen.

Gruß marv
GwenDragon
 2007-04-27 20:30
#37519 #37519
User since
2005-01-17
14790 Artikel
Admin1
[Homepage]
user image
Du liest also gepuffert z. B. mit $socket->read($nachricht, 4096); ein?
tolgale
 2007-04-28 02:17
#37520 #37520
User since
2007-04-24
22 Artikel
BenutzerIn
[default_avatar]
[quote=Guest,27.04.2007, 16:07]Weiterhin muss ich wissen, ob es eine Möglichkeit gibt den Buffer (mit den Serverantworten) zu flushen.[/quote]

$| = 1;


und somit werden die nachrichten direkt übermittelt ( mit der true belegung der variable wird nach jedem print/write der buffer geflusht ).

io::socket :

$sock->autoflush();


http://www.tu-chemnitz.de/docs....toflush\n\n

<!--EDIT|tolgale|1177712473-->
$nobody==$perfect?$everybody==nobody$:$everybody==$perfect; # <(^^,)>
der-marv
 2007-04-29 14:53
#37521 #37521
User since
2007-04-29
1 Artikel
BenutzerIn
[Homepage] [default_avatar]
@GwenDragon: Ja so mache ich das.

@tolgale: Diese Methode habe ich bereits getestet. Auch dann wird der Buffer mit den Serverantworten nicht geflushed... Ich glaube das gilt nur für den sendenden Socket... Aber autoflush ist ja seit Version 1.8 default auf 1.

Sonst noch Ideen?
esskar
 2007-04-29 14:58
#37522 #37522
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
du kannst mit IO::Select prüfen, ob auf dem socket noch daten zum lesen anliegen.
Ansonsten gibt die zahl bei read nur an, wieviel du maximal lesen willst.
heißt, wenn nur 1 byte zum lesen dar sind, liesst du auch nur 1 byte, auch wenn du 4096 bytes angibst.

also, immer mit IO::Select prüfen, ob was zum lesen da ist, und dann lesen
bloonix
 2007-04-29 15:07
#37523 #37523
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Hallo marv,

[quote=Guest,27.04.2007, 16:07]Aber setzt vorraus das ich die LÄNGE kenne...[/quote]
also ich habe mich beim Datenaustausch zwischen Client-Server für
das Konstrukt CPAN:IO::Socket::SSL, CPAN:Storable, CPAN:Safe,
Perldoc:read(), Perldoc:pack() und Perldoc:unpack() entschieden.

Mit Storable kann man Perlstrukturen serialisieren, was andere Scripts
mit Safe und Storable wieder zusammen setzen können. Mit pack() und
unpack() werden die Daten gepackt und entpackt. So weiß man auch,
wieviel Bytes gesendet wurden und kann das recht gut kontrollieren.

Hier ein Beispiel, wie man Daten versenden könnte:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
use Storable qw(nfreeze);

# Wir wollen einen Hash senden
my $data = { foo => 1, bar => 2 };

# Die Daten werden mit Storable::nfreeze serialisiert
$data = nfreeze($data);

# Dann werden die Daten gepackt
$packet = pack("N/a*", $data);

# und zu guter letzt an den Client gesendet
print $socket $packet or die $!;


Als nächstes ein Beispiel, wie man die Daten verarbeiten kann, die
vom Client oder Server gesendet wurden:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use Storable qw(thaw);
use Safe;

# Storable nutzt Eval, dass wollen wir aber aus Sicherheitsgruenden
# nicht, deshalb sind wir mal so frech und ersetzen es einfach
# durch Safe::reval :-)
my $safe = new Safe;

$safe->permit(qw(:default require));

{  # 'once' scope
  no warnings 'once';
  $Storable::Deparse = 1;
  $Storable::Eval = sub { $safe->reval($_[0]) };
}

# Es duerfen maximal 512 KB vom Server gesendet werden. Diesen Wert kann
# man natuerlich beliebig setzen.
my $maxbyt  = 522488;

my ($buffer, $length, $bytes);

# Als erstes lesen wir 4 bytes aus dem Buffer. Diese 4 Bytes werden
# mit unpack entpackt, damit wir wissen, wieviel Bytes noch gesendet
# werden.
$bytes = read($socket, $buffer, 4);
die "read only $bytes/4 bytes from buffer" unless $bytes == 4;
$length = unpack("N", $buffer);

# 512 kilobytes ist das aboslute Maximum, was uns der Server/Client senden darf
die "the maximum size of bytes exceeded: $length" if $length > $maxbyt;
die "no data in buffer" unless $length;

# Jetzt lesen wir den Rest vom Socket in einer Schleife... der Grund fuer
# die Schleife ist, dass sich im Buffer maximal 16384 Bytes befinden
# koennen. Wenn mehr als 512 KB gesendet werden, brechen wir ab.
# Notiz: wenn weniger als 16384 Bytes im Buffer liegen, dann wird
# der Rest gelesen. In $bts stehen immer genau soviele Bytes
# drin, wie tatsächlich von read() gelesen wurde.
$buffer = '';
$bytes  = 0;

while (my $bts = read($socket, my $buf, 16384)) {
  $bytes  += $bts; # Anzahl der bisher gelesenen Bytes
  $buffer .= $buf; # Stück für Stück zusammen setzen
  last if $bytes == $length;

  # Hier wird geprueft, dass der Buffer keinesfalls groesser als
  # 512 KB an Daten enthaelt.
  die "the maximum size of bytes is overtaken" if $bytes > $maxbyt;
}

# Falls read() nichts mehr zurückgibt und die Schleife verlassen wird,
# ist es gut möglich, dass nicht alle Daten gelesen wurden.
die "read only $bytes/$length bytes from client" unless $bytes == $length;

# Die Daten werden mit thaw() rekonstruiert.
my $data = thaw($buffer) or die "unable to rebuild data ($!)";


Das sind alles ein Paar angepasste Codestückchen von mir selber.
Codefehler seien mir vergeben... aber an sich ist es nicht schlecht.

Ich habe auch mal vor einiger Zeit einen Bugreport eröffnet, weil ich
ein paar Probleme hatte. Da wird das gesamte Konstrukt vom Autor
von CPAN:IO::Socket::SSL kurz angeschnitten. Siehe hier:
rt.cpan.org ... id=23419

Gruss,
opi\n\n

<!--EDIT|opi|1177878163-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
<< >> 6 Einträge, 1 Seite



View all threads created 2007-04-27 18:07.