Sockets

M

Monty

Hope this is the right forum for this...

I'm trying to learn sockets, and I'm studying some examples given
vrious places on the web. So far I'm with the explanations, but one
example leaves me perplexed and I'm hoping some one can shed light on
it. I'm hoping to write a chat-like client-server program, and I
found this explanatory code:

.... create socket as before ...
11 use IO::Select;
12 $read_set = new IO::Select(); # create handle set for reading
13 $read_set->add($s); # add the main socket to the set
14
15 while (1) { # forever
16 # get a set of readable handles (blocks until at least one handle
is ready)
17 my ($rh_set) = IO::Select->select($read_set, undef, undef, 0);
18 # take all readable handles in turn
19 foreach $rh (@$rh_set) {
20 # if it is the main socket then we have an incoming connection
and
21 # we should accept() it and then add the new socket to the
$read_set
22 if ($rh == $s) {
23 $ns = $rh->accept();
24 $read_set->add($ns);
25 }
26 # otherwise it is an ordinary socket and we should read and
process the request
27 else {
28 $buf = <$rh>;
29 if($buf) { # we get normal input
30 # ... process $buf ...
31 }
32 else { # the client has closed the socket
33 # remove the socket from the $read_set and close it
34 $read_set->remove($rh);
35 close($rh);
36 }
37 }
38 }
39 }

Some of you probably recognize this.

Regardless of your own opinion of this code, I'm wondering about the
$read_set and $rh_set variables defined here. Are they, in the perl-
ative or figurative sense, lists or arrays containing socket or file
handles? I don't quite follow the perldoc on IO::Select to figure
this out. Also, can sockets generated this way (using IO::Socket) be
bidirectional?

Thanks
 
B

Bernard Chan

Monty said:
... create socket as before ...
11 use IO::Select;
12 $read_set = new IO::Select(); # create handle set for reading
13 $read_set->add($s); # add the main socket to the set
14
15 while (1) { # forever
16 # get a set of readable handles (blocks until at least one handle
is ready)
17 my ($rh_set) = IO::Select->select($read_set, undef, undef, 0);

My opinion: I have personally considered can_read() of IO::Select easier to
use and understand. Any reason to use IO::Select->select() instead?
26 # otherwise it is an ordinary socket and we should read and
process the request
27 else {
28 $buf = <$rh>;
29 if($buf) { # we get normal input
30 # ... process $buf ...
31 }

The code is mixing buffered and non buffered IO. Watch out for surprises due
to unexpected buffering at the PerlIO layer. If I don't get it wrong (I
have done some investigation around sockets and IO::Select recently),
IO::Select works underneath the Perl buffering layer while <> (or
getline()) works with buffering. So it is possible that multiple lines are
read physically from the socket in one go and cached in the buffer, so
IO::Select reports nothing more to read, although you have only read a
single line from the buffer. I/O may then potentially block. I have an
experiment recently which cost me a day to figure it out.
Also, can sockets generated this way (using IO::Socket) be
bidirectional?

Sure. You can read from and write to the same socket, unless you have called
shutdown() on it to change its duplex nature.
 
M

Martien verbruggen

Hope this is the right forum for this...

I'm trying to learn sockets, and I'm studying some examples given
vrious places on the web. So far I'm with the explanations, but one
example leaves me perplexed and I'm hoping some one can shed light on
it. I'm hoping to write a chat-like client-server program, and I
found this explanatory code:

... create socket as before ...
11 use IO::Select;
12 $read_set = new IO::Select(); # create handle set for reading
[snip]

17 my ($rh_set) = IO::Select->select($read_set, undef, undef, 0);
18 # take all readable handles in turn
19 foreach $rh (@$rh_set) {
[snip]

Regardless of your own opinion of this code, I'm wondering about the
$read_set and $rh_set variables defined here. Are they, in the perl-
ative or figurative sense, lists or arrays containing socket or file
handles? I don't quite follow the perldoc on IO::Select to figure
this out.

$read_set is an IO::Select object (see code line 12) and $rh_set is a
reference to an array of file handles that are ready to read. You use
$read_set by using the documented interface of IO::Select, and you use
$read_set by dereferencing it, and doing something with each file
handle.

A list, in Perl, is not something you can store in a variable. It's a
syntactic construct, or a runtime construct, but not a thing you can
store or manipulate. Also see the question 'What is the difference
between a list and an array?' in the Perl FAQ, section 4.

You say 'regardless of your own opinion of this code', but do you really
believe you can post code and not get comments? :)

The code you submitted is a bit of an odd circumvention of the neat OO
interface to select that IO::Select gives you. A better, and more
elegant example which does almost exactly the same as your code, can be
found at the end of the IO::Select man page. I'd use that instead as
your model of how to work with IO::Select, and I'd forget this one.
Also, can sockets generated this way (using IO::Socket) be
bidirectional?

I don't see why not.

Martien
 
M

Monty

Ok, having read the IO::Select perldoc, I can make some sense out of
what it's telling me, and the sample code seems clearer than what I've
found on the web (you're right Martien: how could I NOT expect
comments on any code posted :) ). A couple of things still elude me,
though. If I understand correctly, the sample code in the perldoc
creates a new socket object with $lsn = IO::Socket::INET(etc...) and
then a new IO::Select object is created with $sel = IO::Select($lsn).
With that latter statement, my understanding is that an array-like
object named $sel is created, and $sel can/will contain file handles
to communications streams going through the socket object, $lsn.

Before I go on, am I correct so far?
 
X

xhoster

Monty said:
Ok, having read the IO::Select perldoc, I can make some sense out of
what it's telling me, and the sample code seems clearer than what I've
found on the web (you're right Martien: how could I NOT expect
comments on any code posted :) ). A couple of things still elude me,
though. If I understand correctly, the sample code in the perldoc
creates a new socket object with $lsn = IO::Socket::INET(etc...) and
then a new IO::Select object is created with $sel = IO::Select($lsn).

Yes. The first creates a socket that listens for incoming connections.
The second lets you listen for those incoming connections without blocking.
With that latter statement, my understanding is that an array-like
object named $sel is created,

I have no idea what *you* consider to be "array-like". $sel is an
IO::Select object. If IO::Select objects are "array-like" to you, then it
is array-like. But I suspect you will find it less confusing to just accept
that IO::Select is what it is, rather than trying to force it into
classifications like "array-like"
and $sel can/will contain file handles
to communications streams going through the socket object, $lsn.

$sel "contains" file handles. Initially, $lsn is the only file handle it
contains. As the code operates, new file handles (sockets created by
accepting connections negotiated through $lsn) are added to $sel. These
new connections, once established, are no longer related to $lsn.

So "$sel->can_read" is basically saying "Wait either for a new connection
to be ready to be accepted, or until one of the already accepted
connections has sent me data"

Xho
 
M

Martien verbruggen

So what is it?

It is mainly an IO::Select object, i.e. you use it in accordance with
the IO::Select documentation, generally by calling methods on it.

It is also a reference blessed into the IO::Select class, but that's
just the way perl implements OO.

What it is a reference to (and that may very well be an array, but more
commonly a hash is used) is not important, unless you have to modify the
code of IO::Select itself. Actually, I just checked, and IO::Select
objects are indeed references to arrays, but again, it doesn't matter.

One of the points of OO classes is to encapsulate and hide the
implementation from the user of the class. It should never be necessary
to need to know what exactly underlies the implementation.

If you want to know, however, a quick look at the code is often the best
way to find out. I used perldoc -m IO::Select to check.

Martien
 
M

Monty

Actually, I just checked, and IO::Select
objects are indeed references to arrays, but again, it doesn't matter.

Actually, to me, at this stage of understanding, it kind of does
matter that it's an array. While it could have been an array, a list,
or a hash, those structures are at least familiar and I know means
exist for traipsing through them. So now the statement @ready = $sel-
can_read begins to shed light for me.
One of the points of OO classes is to encapsulate and hide the
implementation from the user of the class. It should never be necessary
to need to know what exactly underlies the implementation.

In practice, I won't need to refresh myself with the underlying
mechanisms, but they are important to learn from.

So this is what I've got from all this so far: IO::Select allows me to
'peruse', if you will, all the connections associated with a port I
designate in a client-server connection, upon or through which I've
established a communications socket (bear with me if this is rambling
a bit). Somewhere in the system, something is keeping track of all
the connections I establish through that port, and IO::Select helps me
look at them all.

How's that so far?
 
M

Martien verbruggen

Actually, to me, at this stage of understanding, it kind of does
matter that it's an array. While it could have been an array, a list,
or a hash, those structures are at least familiar and I know means
exist for traipsing through them. So now the statement @ready = $sel-

But that doesn't actually have anything to wo with what the IO::Select
object is. It simply has to do with what the can_read method in the
IO::Select package returns. It returns a list of file handles ready for
reading. That list is then stored in the array @ready.
In practice, I won't need to refresh myself with the underlying
mechanisms, but they are important to learn from.

Learning is good. But you do need to make sure that you're learning the
right things. Starting with the basics -- and someone else has already
suggested a list of documents to start with -- is important, before you
start to read OO module code, which can be, and often is, rather terse
and sometimes somewhat obscure.
So this is what I've got from all this so far: IO::Select allows me to
'peruse', if you will, all the connections associated with a port I
designate in a client-server connection, upon or through which I've
established a communications socket (bear with me if this is rambling
a bit). Somewhere in the system, something is keeping track of all
the connections I establish through that port, and IO::Select helps me
look at them all.

How's that so far?

Sort of ok-ish :)

IO::Select is one of the ways to package up a load of file handles, and
check them in bulk.

The file handles are most often connected to sockets, but don't have to
be. They are most often all of the same type, but they don't have to be.

But in the most used configuration, IO::Select does what you describe.
So, by the way, does the perl builtin select. IO::Select just gives you
a much nicer and easy to use interface.

Martien
 
M

Monty

Ok, so I'm not too far off on my thinking. If you'd be so kind, I'd
like to 'talk out' the level of understanding I have about sockets,
ports, and maybe ask, later, about these file handles associated with
them. Some how I'm a bit surprised that the can_read method of
IO::Select in regards to sockets involves file handles (not entirely
surprised; everything in UNIX is a file). I expected something else,
but what else, I don't know.

With the coding of a new IO::Socket::INET I specify, among other
things, a port and a Listen parameter, which in this case is greater
than 1, meaning I can have more than one communication 'stream' that
is separate and distinct from others on that port. The only education
I have along these lines is a brief explanation of FTP, where I'm told
communications between MyComputer and YourComputer are established via
a well-known port (21, I believe) and once the two systems agree to
talk, they also agree to further the conversation on a not-well-known
port, freeing up 21 for further FTP requests.

Is something similar going on with my socket? That would clear up one
part of the mystery.

The second, these file handles, leads me to believe that somewhere on
the system I would expect to find a file designated as a socket (with
Solaris, that designation is noted by the '=' at the end of the file
name). Is that the case?
 
X

xhoster

Monty said:
In practice, I won't need to refresh myself with the underlying
mechanisms, but they are important to learn from.

So this is what I've got from all this so far: IO::Select allows me to
'peruse', if you will, all the connections associated with a port I
designate in a client-server connection,

IO::Select operates on the file handles that you stuff into it. In this
case, such stuffing is done with both the "new" call and in the "add" call.

IO::Select does not know or care how you arrived at the file handles which
you stuff into it. They could come from the same port, from different
ports, from named pipes or other special files, whatever.

upon or through which I've
established a communications socket (bear with me if this is rambling
a bit). Somewhere in the system, something is keeping track of all
the connections I establish through that port,

The "somewhere" and "something" are in the statements:

$sel = new IO::Select( $lsn );

and then later in the

$sel->add($new);

So it isn't the system that is keeping track, it is you, through your
code, who is keeping track.

and IO::Select helps me
look at them all.

It helps you know which ones are immediately available for reading (or, in
the case of $lsn, available for accepting) without blocking.

Xho
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top