- 论坛徽章:
- 1
|
又有一个select或fork都不好搞的问题!
一個multiplexed client
$!/usr/bin/perl
use strict;
use IO::Select;
use IO::Select;
use constant BUFSIZE=>;1024;
my $host = shift or die "Usagexx.pl host [port]\n";
my $port = shift || 'echo';
my $socket= IO::Socket::INET->;new("$hostport" or die $@;
my $readers = IO::Select->;new or die "can't create IO::Select read object";
$readers->;add(\*STDIN);
$readers->;add($socket);
my $buffer;
while(1){
my @ready = $readers->;can_read;
for my $handle (@ready){
if($handle eq \*STDIN){
if(sysread(STDIN,$buffer,BUFSIZE)>; 0){
syswrite($socket,$buffer);
}else{
$socket->;shutdonw(1);
}
}
if($handle eq $socket){
if(sysread($socket,$buffer,BUFSIZE) >;0){
syswrite(STDOUT,$buffer);
}else{
warn "Connection close by foreign host.\n";
exit 0;
}
}
}
這是個以tcp為例的代碼...
書上有提到..用<>;速度會比較慢.
.如果為了效能起見..用sysread、syswrite比較好..
另外udp用的是send與recv..跟..tcp用的不一樣哩...
#!/usr/bin/perl
use strict;
use IO::Socket;
use IO::Select;
use IO::Getline;
use constant MAS_MSG_LEN =>; 5000;
use constant TIMEOUT =>; 2;
use constant MAX_RETRIES =>; 5;
my %PENDING; # hash of requests indexed by sequence number
use constant REQUESTs =>; 0; # with these two fields
use constant TRIES =>; 1;
# keep track of outgoing and incoming sequence numbers
my $seqout = 0;
my $seqin = 0;
my $host = shift||'localhost';
my $port = shift || 'echo';
my $sock = IO::Socket::INET->;new(Proto=>;'udp', PeerAddr=>;"$hostport"
or die $@;
my $select = IO::Select->;new($sock,\*STDIN);
my $stdin = IO::Getline->;new(\*STDIN);
LOOP:
while(1){
my @ready = $select->;can_read(TIMEOUT);
for my $handle (@ready){
if($handle eq \*STDIN){
my $length = $stdin->;getline($_) || last LOOP;
next unless $length>;0;
chomp;
send_message($seqout++,$_);
}
if($handle eq $sock){
my $data;
$sock->;recv($data,$MAX_MSG_LEN) || die "recv() : $!\n";
receive_message($data);
}
}
# handle any leftover messges on timeout events
do_retries() unless @ready;
}
sub send_message{
my ($sequence,$msg) = @_;
# send the message
$sock->;send("$sequencemsg" or die "send(): $! \n";
# mark this as pending
$PENDING{$sequence}[$REQUEST] = $msg;
$PENDING{$sequenct}[TRIES]++;
}
sub receive_message{
my $message = shift;
my($sequence,$msg) = $message=~ /^(\d+).*)/
|| return wrarn "bad format message '$message'!\n";
#die we ask for this
unless($PENDING{$sequence}){
warn "Discarding duplicate message seqno = $sequence\n";
return;
}
# warn about out of order messages
warn "Out of order message seqno = $sequence\n" if $sequence <$seqin;
# print result
print $PENDING{$seqence}[REQUEST],' =>; ',',$msg,"\n";
#remember last sequence number, and remove message from pending
$seqin = $sequence;
delete $PENDING{$sequence};
}
sub do_retries{
for my $seq (keys %PENDING){
if($PENDING{$seq}[TRIES] >;= MAX_RETRIES){
warn "$seq: too many retries. Giving up.\n";
delete $PENDING{$seq};
next;
}
warn "$seq:retrying...\n";
send_message($seq,$PENDING{$seq}[REQUEST]);
}
}
看看對你有沒有幫助.... |
|