Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]4286[/thread]

Probleme mit Client



<< >> 10 Einträge, 1 Seite
Gast Gast
 2004-05-17 18:37
#37011 #37011
Schau mal im 'Perl Kochbuch' nach - wenn ich mich recht erinnere dann ist der Code für den Server den Du suchst dort abgebildet.
Link: Alle Code-Beispiele aus dem Kochbuch
Eine andere gute Quelle ist 'Netzwerk-Programierung mit Perl' von Lincoln S. Stein\n\n

<!--EDIT|Dieter|1084805284-->
Gast Gast
 2004-05-17 18:52
#37012 #37012
Dann schau Dir mal Kapitel 17.10 an ...
'Entwicklung von bidirektionalen Clients'
sri
 2004-05-18 16:39
#37013 #37013
User since
2004-01-29
828 Artikel
BenutzerIn
[Homepage] [default_avatar]
Non-blocking IO is ja im moment mein Lieblingsthema. :)

Ich würde dir auf jeden Fall auch zu POE raten!!!

Aber hier ein Beispiel mit IO::Poll, das buffern und die sysread/syswrite teile sind bei einer select() Lösung ja identisch.

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/usr/bin/perl
# usage: client.pl [host] [port]

use strict;
use IO::Socket;
use IO::Poll 0.04 qw(POLLIN POLLOUT POLLERR POLLHUP);
use Errno qw(EWOULDBLOCK);
use constant MAXBUF => 8192;
$SIG{PIPE} = 'IGNORE';
my ($to_stdout,$to_socket,$stdin_done,$sock_done);

my $host = shift or die "Usage: client.pl host [port]\n";
my $port = shift || 'echo';
my $socket = IO::Socket::INET->new("$host:$port") or die $@;

my $poll = IO::Poll->new() or die "Can't create IO::Poll object";
$poll->mask(\*STDIN => POLLIN);
$poll->mask($socket => POLLIN);

$socket->blocking(0); # turn off blocking on the socket
STDOUT->blocking(0); # and on STDOUT

while ($poll->handles) {

$poll->poll;

#handle readers
for my $handle ($poll->handles(POLLIN|POLLHUP|POLLERR)) {

if ($handle eq \*STDIN) {
$stdin_done++ unless sysread(STDIN,$to_socket,2048,length $to_socket);
}

elsif ($handle eq $socket) {
$sock_done++ unless sysread($socket,$to_stdout,2048,length $to_stdout);
}
}

# handle writers
for my $handle ($poll->handles(POLLOUT|POLLERR)) {

if ($handle eq \*STDOUT) {
my $bytes = syswrite(STDOUT,$to_stdout);
unless ($bytes) {
next if $! == EWOULDBLOCK;
die "write to stdout failed: $!";
}
substr($to_stdout,0,$bytes) = '';
}

elsif ($handle eq $socket) {
my $bytes = syswrite($socket,$to_socket);
unless ($bytes) {
next if $! == EWOULDBLOCK;
die "write to socket failed: $!";
}
substr($to_socket,0,$bytes) = '';
}
}

} continue {
my ($outmask,$inmask,$sockmask) = (0,0,0);

$outmask = POLLOUT if length $to_stdout > 0;

$inmask = POLLIN unless length $to_socket >= MAXBUF
or ($sock_done || $stdin_done);

$sockmask = POLLOUT unless length $to_socket == 0 or $sock_done;
$sockmask |= POLLIN unless length $to_stdout >= MAXBUF or $sock_done;

$poll->mask(\*STDIN => $inmask);
$poll->mask(\*STDOUT => $outmask);
$poll->mask($socket => $sockmask);

$socket->shutdown(1) if $stdin_done and !length($to_socket);
}
\n\n

<!--EDIT|sri|1084884090-->
steve
 2004-05-18 19:20
#37014 #37014
User since
2004-03-04
52 Artikel
BenutzerIn
[default_avatar]
guck dir einfach IO:Select an. Damit ist sowas nicht schwer.

steve
naich
 2004-05-17 18:15
#37015 #37015
User since
2004-05-17
8 Artikel
BenutzerIn
[default_avatar]
Hey,

ich habe folgendes Problem bei einem kleinen Client/Server - Projekt.
Ich habe einen Select - Server geschrieben, der seine Sache ganz gut macht. Mein Problem ist der Client.
Sobald ich im Client ein Text eingeben will (der dann beim Server verarbeitet werden soll) wird ja die STDOUT blockiert und er kann somit keine Daten empfangen.
Gibt es eine Möglichkeit mit fork, besser aber mit select den Client nicht blockieren zu lassen? (also quasi gleichzeitiges senden und empfangen wie beim Server)

Ich danke euch schon mal. Falls ihr noch mehr Infos braucht, gebe ich sie natürlich gerne. :)

MfG
naich\n\n

<!--EDIT|naich|1084803695-->
naich
 2004-05-17 18:46
#37016 #37016
User since
2004-05-17
8 Artikel
BenutzerIn
[default_avatar]
Den Server hab ich ja schon (aus dem Kochbuch ;) ), aber mir fehlt jetzt der Client.
Strat
 2004-05-17 20:12
#37017 #37017
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
schau dir mal POE an....

sonst hilft vielleicht CPAN:IO::Nonbocking
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
naich
 2004-05-18 18:24
#37018 #37018
User since
2004-05-17
8 Artikel
BenutzerIn
[default_avatar]
Dies ist mein bisheriger Client. Also wirklich sehr schlicht gehalten. Aber der wartet ständig auf eingehende Daten, die selten kommen.


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
#!/usr/bin/perl -w
use strict;
use IO::Socket;
use IO::File;
use Switch;
use Data::Dumper;

my $peerAddr; # that's the hosts ip-adress
my $peerPort; # that's the hosts port
# the usage is: command ip-addr port

if ($ARGV[0] && $ARGV[1])
{
$peerAddr = $ARGV[0];
$peerPort = $ARGV[1];
}
else
{
die "Usage: $0 target-address portnumber\n";
}

# CREATING THE SOCKET
my $server = new IO::Socket::INET (
PeerAddr => $peerAddr,
PeerPort => $peerPort,
Proto => "tcp",
Type => SOCK_STREAM
) or die "*** Can't connect to server. ($!) ***\n";

my $maxBuffer = 1024;
my $myName;

# CREATING THE FORK

my $pid = fork();                  # the fork lets us create two parallel processes

if ($pid == 0) { # when our process is active -> do something
main("start","");
} else { # otherwise -> read out the server's messages
while(1) {
my $nval = $server->recv(my $data, $maxBuffer, 0);
if (defined($nval) && length($data))
{
XMLparse($data);
}
}
}
$server->close();
exit;




Danke sri für das aufwendige Beispiel, bei dem schau ich aber noch nicht ganz durch. Wo werden beim dem Beispiel die Daten übertragen.
Ich muss in meinem Client ein XML-String übertragen. Könntest du oder jemand anders mit 2 Kommentaren die stellen mir nochmals deutlich machen. z.B. #xmlinput bzw. #xmloutput

Danke für eure Mühe.\n\n

<!--EDIT|naich|1084890497-->
naich
 2004-05-18 19:34
#37019 #37019
User since
2004-05-17
8 Artikel
BenutzerIn
[default_avatar]
Der Server läuft ja auf IO::Select.

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
my $socket = new IO::Socket::INET (
LocalHost => $hostAddr,
LocalPort => $hostPort,
Proto => 'tcp',
Type => SOCK_STREAM,
Listen => SOMAXCONN,
Reuse => 1
) or die "*** Can't create server socket. ($!) ***\n" unless $socket;
print "*** Server listening on $hostAddr:$hostPort ... :-) ***\n";

my $allClients = new IO::Select($socket);
my @activeClients;

while (@activeClients = $allClients->can_read())
{
foreach my $client (@activeClients)
{
if ($client eq $socket)
{
my $newClient = $socket->accept(); # accept the connection
$allClients->add($newClient); # add it to the handler
print "*** ".$newClient->peerhost.":".$newClient->peerport." has just connected. ***\n";
}
else
{
my $nval = $client->recv(my $request, $maxBuffer, 0);
if (!defined($nval) || !length($request))
{
print "*** Connection has been closed. ***\n";
my $h = 0;
while ($activeUsers[$h])
{
if ($activeUsers[$h]->{'handle'} == $client)
{
splice(@activeUsers,$h,1);
}
$h++;
}
$allClients->remove($client);
$client->close();
next;
}
}
}
}



Aber wie sieht das auf der Client-Seite aus. Da kann ich ja nicht auf eigende Verbindungen warten.
So langsam verzweifele ich an dem Problem.
sri
 2004-05-18 20:43
#37020 #37020
User since
2004-01-29
828 Artikel
BenutzerIn
[Homepage] [default_avatar]
[quote=naich,18.05.2004, 17:34]Der Server läuft ja auf IO::Select.[/quote]
Und ist blocking!!!

Code: (dl )
$socket->blocking(0);


Das fehlt!

Aus meinem Beispiel schnapp dir einfach die sysread/syswrite Blöcke oder benutz besser POE. ;)
<< >> 10 Einträge, 1 Seite



View all threads created 2004-05-17 18:37.