J
jari.eskelinen
Hi there,
I am having wirting simple server-client program with
ActiveState ActivePerl 5.8.7 in Win32, but having some
weird problems with reading from sockets. I have googled
for a day now and have found no solution.
I am using line-based communication in order to keep
reading and writing to sockets easy and to avoid buffering
problems. However, buffering problems I have:
When I write two lines from server to socket and do
IO::Select::select (or can_read()) in client, select()
returns handle that can be read. I read first line from
socket using <$socket> and then select() again. Select should
return again handle because there are unread second line.
However, it wil not return anything. If I read from socket
despite of select()'s reutrn, I get second line just like
expected.
So behaviour of select() is unexpected. Or should select()
behave like that? Returning filehandle that can be read only
once, even if there are more data? I read select()'s
documentation, but got an image that it should return handles
ALWAYS if there are data available.
What I am doing wrong? Thank you very much in advance if
somebody can give answer to me!
Ps. Code for reproducing problem:
--------- server.pl -----------
#!/usr/bin/perl -w
use strict;
use IO::Socket;
use IO::Select;
my $socket = new IO::Socket::INET(
LocalAddr=>'localhost',
LocalPort=>'1234',
Proto=>'TCP',
Listen =>1);
binmode($socket);
$socket->autoflush(1);
my $select = new IO::Select();
$select->add($socket);
while (1) {
my @readable = $select->can_read(0);
foreach my $rsock (@readable) {
if ($rsock == $socket) {
my $ns = $rsock->accept();
binmode($ns);
$ns->autoflush(1);
$select->add($ns);
print {$ns} "Hello there, I am your server.\r\n";
print {$ns} "Ready to obey?.\r\n";
} elsif (eof($rsock)) {
$select->remove($rsock);
close($rsock);
} else {
my $buffer = <$rsock>;
print "Client said: $buffer\n";
}
}
sleep(1);
}
----------------------------------
----------- client.pl ------------
#!/usr/bin/perl -w
use strict;
use IO::Socket;
use IO::Select;
use Data:umper;
my $socket = new IO::Socket::INET(
PeerAddr=>'localhost',
PeerPort=>'1234',
Proto=>'TCP',
);
binmode($socket);
$socket->autoflush(1);
my $select = new IO::Select();
$select->add($socket);
while (1) {
my @readable = $select->can_read(0);
print Dumper \@readable;
foreach my $rsock (@readable) {
my $buffer = <$rsock>;
print "Server said: $buffer\n";
}
sleep(1);
}
----------------------------------
When running server.pl and client.pl, client prints following:
$VAR1 = [];
$VAR1 = [
bless( \*Symbol::GEN0, 'IO::Socket::INET' )
];
Server said: Hello there, I am your server.
$VAR1 = [];
$VAR1 = [];
Etc. It is cleary seen that select() (or in this case can_read())
indicates that there are nothing more to read, even when there are.
Best regards,
Jari Eskelinen
I am having wirting simple server-client program with
ActiveState ActivePerl 5.8.7 in Win32, but having some
weird problems with reading from sockets. I have googled
for a day now and have found no solution.
I am using line-based communication in order to keep
reading and writing to sockets easy and to avoid buffering
problems. However, buffering problems I have:
When I write two lines from server to socket and do
IO::Select::select (or can_read()) in client, select()
returns handle that can be read. I read first line from
socket using <$socket> and then select() again. Select should
return again handle because there are unread second line.
However, it wil not return anything. If I read from socket
despite of select()'s reutrn, I get second line just like
expected.
So behaviour of select() is unexpected. Or should select()
behave like that? Returning filehandle that can be read only
once, even if there are more data? I read select()'s
documentation, but got an image that it should return handles
ALWAYS if there are data available.
What I am doing wrong? Thank you very much in advance if
somebody can give answer to me!
Ps. Code for reproducing problem:
--------- server.pl -----------
#!/usr/bin/perl -w
use strict;
use IO::Socket;
use IO::Select;
my $socket = new IO::Socket::INET(
LocalAddr=>'localhost',
LocalPort=>'1234',
Proto=>'TCP',
Listen =>1);
binmode($socket);
$socket->autoflush(1);
my $select = new IO::Select();
$select->add($socket);
while (1) {
my @readable = $select->can_read(0);
foreach my $rsock (@readable) {
if ($rsock == $socket) {
my $ns = $rsock->accept();
binmode($ns);
$ns->autoflush(1);
$select->add($ns);
print {$ns} "Hello there, I am your server.\r\n";
print {$ns} "Ready to obey?.\r\n";
} elsif (eof($rsock)) {
$select->remove($rsock);
close($rsock);
} else {
my $buffer = <$rsock>;
print "Client said: $buffer\n";
}
}
sleep(1);
}
----------------------------------
----------- client.pl ------------
#!/usr/bin/perl -w
use strict;
use IO::Socket;
use IO::Select;
use Data:umper;
my $socket = new IO::Socket::INET(
PeerAddr=>'localhost',
PeerPort=>'1234',
Proto=>'TCP',
);
binmode($socket);
$socket->autoflush(1);
my $select = new IO::Select();
$select->add($socket);
while (1) {
my @readable = $select->can_read(0);
print Dumper \@readable;
foreach my $rsock (@readable) {
my $buffer = <$rsock>;
print "Server said: $buffer\n";
}
sleep(1);
}
----------------------------------
When running server.pl and client.pl, client prints following:
$VAR1 = [];
$VAR1 = [
bless( \*Symbol::GEN0, 'IO::Socket::INET' )
];
Server said: Hello there, I am your server.
$VAR1 = [];
$VAR1 = [];
Etc. It is cleary seen that select() (or in this case can_read())
indicates that there are nothing more to read, even when there are.
Best regards,
Jari Eskelinen