Schrift
[thread]4294[/thread]

TCP Client - Socket lesen und schliessen (Seite 2)

Leser: 1


<< |< 1 2 3 >| >> 30 Einträge, 3 Seiten
steffenw
 2004-08-20 01:24
#37537 #37537
User since
2003-08-15
692 Artikel
BenutzerIn
[Homepage] [default_avatar]
Bei Sockets nimm nie read, sondern nur $socket->recv() oder sysread(...) nie print, sondern immer $socket->send() oder syswrite(). Sonst wird vom System fleißig gepuffert und Du bekommst nie eine Antwort.
$SIG{USER} = sub {love 'Perl' or die};
esskar
 2004-08-20 01:28
#37538 #37538
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
und falls die größe deiner daten doch varieren kann, kannst du mit select feststellen, ob du vom socket lesen kannst
Reinhard
 2004-08-20 17:54
#37539 #37539
User since
2004-08-18
16 Artikel
BenutzerIn
[default_avatar]
Hallo Dirk, sk und steffenw
danke für Eure Hilfe und Informationen. Das mit select hört sich gut an, jedoch scheint es auf Windows nicht zu funktionieren (ich bekomme immer ein leeres Array zurück) oder ich hab es noch nicht verstanden. Auch den Socket auf non-blocking zu stellen, löst nicht mein Schleifenproblem.
Mein jetziger COde sieht so aus
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
use strict;
use Config;
use IO::Socket::INET;
use IO::Select;

my $SocketHandle;
my $buf;
my $binFile  = "<e:/test.bin";
my $Status;
my $SelHandle;
my @Readable;

unless (@ARGV == 2) { die "Usage: GetStatus.pl remotehostname port" }

$SocketHandle = IO::Socket::INET->new(PeerAddr =>  $ARGV[0],
                                     PeerPort =>  $ARGV[1],
                                     Proto    =>  "tcp",
                                     Timeout  =>  10,
                                     Type     =>  SOCK_STREAM) or die "cannot connect: $!\n";
$SocketHandle->autoflush(1);
$SocketHandle->blocking(0);

open(FileHandle, $binFile)or die "cannot open file: $!\n";
binmode(FileHandle);

while (read(FileHandle, $buf, 28))
{
   $SocketHandle->send($buf);
}

$|=1;

$SelHandle = IO::Select->new($SocketHandle);

while (@Readable = $SelHandle->can_read)
{
$SocketHandle->recv($Status,1);
print($Status);
}

close FileHandle;
close $SocketHandle;


Danke
Reinhard
Reinhard
 2004-08-21 00:07
#37540 #37540
User since
2004-08-18
16 Artikel
BenutzerIn
[default_avatar]
Hallo steffenw,

danke für den Hinweis, mein Problem ist aber nicht beim senden, sondern beim empfangen.
Weisst Du ob es eine Möglichkeit gibt beim recv die zu empfangenen Bytes zu ermitteln?

Danke
Reinhard
Reinhard
 2004-08-21 01:06
#37541 #37541
User since
2004-08-18
16 Artikel
BenutzerIn
[default_avatar]
Hallo,

das mit dem Denkfehler war mein erstes Problem, deshalb die while schleife.

Code: (dl )
1
2
3
4
5
while (@Readable = $SelHandle->can_read)
{
$SocketHandle->recv($Status,1);
print($Status);
}

Nur aus dieser Schleife komme ich nicht mehr raus.
Die Daten sind da, kein Problem.
Ein momentaner Workaround ist, dass ich nicht mit der while Schleife arbeite, sondern fest die Länge von 1024 Characters angebe. Nur was, wenn ich mal mehr als 1024 Buchstaben zurückbekomme, dass ürde ich gerne abfangen.

Danke
Reinhard
Reinhard
 2004-08-23 22:06
#37542 #37542
User since
2004-08-18
16 Artikel
BenutzerIn
[default_avatar]
Hallo steffenw,

ich glaube wir reden aneinander vorbei (oder ich verstehe es nicht).
Wenn Du sagsts: "Das Select sagt Dir nur, daß es etwas zu lesen gibt und nicht wieviel" heisst dass doch, das etwas im Netzwerkpuffer ist und zum lesen bereitsteht. Das heisst doch aber auch, dass irgendwann der Puffer wieder leer ist und dann die Schleife beendet werden müsste.

Durch das testen bin ich aber eher der Meinung, dass select nur prüft, ob ein Socket nicht durch eine Operation wie lesen oder schreiben blockiert ist.

Die 1024 Zeichen sind mein Workaround, da momentan nur ca. 600 Zeichen übertragen werden (variiert +- 20 Zeichen) geht das, was wenn aber irgendwann 1200 Zeichen übertragen werden?

Wenn ich die Schleife benütze, dann bekomme ich die Daten (ich lasse die ausgeben). Ich weiss dann auch, dass ich alles habe (das weiss ich, weil ich es auf dem Blidschirm sehe, nicht programmtechnisch) nur hänge ich weiterhin in der Schleife.

Ich schicke dem Server eine Anfrage und gehe auf Lesemodus, der Server antwortet mir genau einmal. Ich bekomme alle Daten und will nun aus der Schleife.

Um das zu bewerkstelligen müsste ich doch entwerder den TCP Header der empfangenen Daten auslesen um an die übertragenen Bytes zu kommen oder aber.... und hier weiss ich nicht weiter.

Nochmals vielen Dank für Deine Hilfe
Reinhard
Reinhard
 2004-08-26 22:43
#37543 #37543
User since
2004-08-18
16 Artikel
BenutzerIn
[default_avatar]
Hallo steffenw,

ich habe jetzt einen Workaround, mit dem ich wohl leben muss.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
my $maxPacket = 1500;
while ($SocketHandle->recv($Status,$maxPacket))
{
if (length($Status) ne $maxPacket)
{
print $Status;
last;
}
elsif (length($Status) eq $maxPacket)
{
print $Status;
next;
}
}


dieser funktioniert solange nicht die gesendeten Bytes genau 1500 sind. Dann bleibt das Script wieder beim ->recv hängen.

Danke nochmals für Deine Hilfe!
Reinhard
Reinhard
 2004-08-25 20:56
#37544 #37544
User since
2004-08-18
16 Artikel
BenutzerIn
[default_avatar]
Hallo Dirk, hallo steffenw,

entschuldigt wenn ich mich erst jetzt melde.

@Dirk->Danke für den Workaround, damit spiele ich mal ein bisschen

@steffenw->Warst Du nicht derjenige, der mir empfohlen hat nicht read zu nehmen ;-)

und bei der Beschreibung von recv ist diesbezgl. nichts zu finden

Receives a message on a socket. Attempts to receive LENGTH characters of data into variable SCALAR from the specified SOCKET filehandle. SCALAR will be grown or shrunk to the length actually read. Takes the same flags as the system call of the same name. Returns the address of the sender if SOCKET's protocol supports this; returns an empty string otherwise. If there's an error, returns the undefined value. This call is actually implemented in terms of recvfrom(2) system call.

Danke
Reinhard
steffenw
 2004-08-27 02:55
#37545 #37545
User since
2003-08-15
692 Artikel
BenutzerIn
[Homepage] [default_avatar]
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
my $maxPacket = 1500;
...
while (1) {
my @Readable = $SelHandle->can_read(10) or last;   # Timeout 10 Sekunden
foreach my $socket (@Readable) {
# spätestens sinnvoll, wenn andere Handles mit select überwacht werden
  if ($socket eq $SocketHandle) {
    $SocketHandle->recv($Status, $maxPacket)
   # nur Länge 0 ist etwas besonderes, alles andere ist uninteressant
   length $Status or print ("EOF erkannt\n"), last;
    print $Status;
 }
}
}
# wenn Gegenseite kein EOF sendet kommt nach 10 Sekunden der Timeout und Du bist hier.
...
\n\n

<!--EDIT|steffenw|1093636765-->
$SIG{USER} = sub {love 'Perl' or die};
steffenw
 2004-08-28 00:01
#37546 #37546
User since
2003-08-15
692 Artikel
BenutzerIn
[Homepage] [default_avatar]
Oh, meine while-Schleife wurde ja nie abgebrochen, das habe ich gleich mal noch verändert.

Die can_read-Methode antwortet im Timeoutfall mit einem leeren Array und dann kommst Du in meinem Script niemals bei "recv()" an, weil die foreach-Schleife nicht ausgeführt wird. Wenn Du weitere Handles an "select" übergeben hast, dann sorgt spätestens die if-Bedingung für das Umgehen von"recv()".
$SIG{USER} = sub {love 'Perl' or die};
<< |< 1 2 3 >| >> 30 Einträge, 3 Seiten



View all threads created 2004-08-18 19:50.