Help - Search - Member List - Calendar
Full Version: Multitasking
WorkTheWeb Forums > Webmaster Resources > Perl Beginner Help
Support our Sponsors!
Dave W Turner
Hey,

I am making an IRC bot to bridge 2 channels on different networks.
For this I need to scan 2 sockets for data. How do I do this? This
is how I do 1 socket:

while(my $input = <$sock>)
{
.........
}

--

Dave
All us base are belong to you.

Chris Devers
On Wed, 6 Jul 2005 [Email Removed] wrote:

QUOTE
I am making an IRC bot to bridge 2 channels on different networks.

Super. Considered using a CPAN module to save reinventing wheels?

<http://search.cpan.org/~tomi/Bot-BasicBot/lib/Bot/BasicBot.pm>
<http://jerakeen.org/programming/Bot-BasicBot>

It may be that Bot::BasicBot doesn't do what you need, but this wheel
has been reinvented so many times that it's at least worth taking a look
at before you plunge into the madness of manual socket programming :-)

If you're stuck with manual socket work, at least look at the relevant
CPAN modules related to socket programming, e.g.

<http://search.cpan.org/~nwclark/perl-5.8.7/ext/IO/lib/IO/Socket.pm>
<http://search.cpan.org/~nwclark/perl-5.8.7/ext/Socket/Socket.pm>
<http://search.cpan.org/search?query=socket&mode=all>

And if I myself am inventing a wheel that you've already looked at :-),
then please show some more of the code you've already tried & had
trouble with.


--
Chris Devers

Wiggins d'Anconia
[Email Removed] wrote:
QUOTE
Hey,

I am making an IRC bot to bridge 2 channels on different networks.
For this I need to scan 2 sockets for data.  How do I do this?  This
is how I do 1 socket:

while(my $input = <$sock>)
{
.........
}


Ah, a whole 'nother level...

So in general you are talking about multiplexing, and you are probably
best off with picking up a good book on how to do this correctly. I
would highly suggest Network Programming with Perl by Lincoln Stein. The
lowest level (that I know of) way to do this is with the select() function,

perldoc -f select

But that gets *real* hairy, real fast. You might be better off looking
into IO::Select which is standard and has a nice little example on the
doc page.

Though I agree with the other poster that suggested looking into POE and
its components, since a lot of this has already been written. POE
handles multitasking/multiplexing like a dream. If you are doing this to
learn, then kudos. If you are doing this for any other reason then this
is one wheel you don't want to reinvent.

http://danconia.org

Wiggins d'Anconia
Please group reply to prevent getting accidentally ignored and so
everyone can help and be helped. Also please bottom post.

[Email Removed] wrote:
QUOTE
Well, I have tried some modules, etc, but none of them have been
properly documented, or made the documentation available to any
mortals.  After trying out a few, I prefered to do the socket
programming myself.


Which ones? The modules used for this task are going to be pretty
advanced, as the task is, they are likely going to take more than a
cursory glance to figure them out.

QUOTE
If I do use select for sockets, or something, i.e:

while(1)
{
if(my $input = <$sock1>)
{
......
}

if(my $input = <$sock2>)
{
......
}
}

Won't it just sit on $sock1 waiting for data until it gets some,
whilst messages could be pouring in unread on $sock2?


Yes and no. With select you can check whether a filehandle is ready for
reading (or writing, etc.) then you act on it. You don't check for input
by reading the input (thereby avoiding the blocking). After you have
checked to see if it is ready, then you read from it. Having said all of
this you *really* don't want to use the built-in select, definitely use
IO::Select if you don't use something higher level like POE. There is a
very plain and simple example at the bottom of the doc page for IO::Select:

http://search.cpan.org/~nwclark/perl-5.8.7...ib/IO/Select.pm

Though it is more of a server rather than client example. Essentially
you open the filehandles (sockets) you want to read from, add them to an
IO::Select object, then ask that object for a list of handles ready to
be read from. Then just read from the handle. On the same token you
should really be using IO::Socket::* instead of messing with the sockets
directly. If it is good enough for Mr. Stein, it is good enough for
*almost* all of us.

Having said all of this, it still isn't truly multitasking because you
can still block on a socket that had a lot of data or a slow socket.
This method presumes that your CPU and IO handler is fast enough to
prevent the appearance of a slow down because of blocking. To truly
multitask you are going to have to use forks, threads, or similar. POE
again could help with setting these things up which is why I recommend
it. It is a framework specifically designed to handle multitasking with
interesting IO, particularly from sockets. But all of this gets
relatively complex which is why I recommended Network Programming with Perl.

QUOTE
Also, is select necessary - can't you just use each sock my name,
instead of by default?


If I understand the above correctly, yes it is necessary, but I think
you are confusing the 4 argument form of select with the 1 argument
form. Regardless IO::Select hides all of those details.

perldoc -f select

Good luck,

http://danconia.org

Dave W Turner
Uhhh.... I can't believe I just posted it non-list again. Here it is
for the list:

On 7/8/05, Wiggins d'Anconia <[Email Removed]> wrote:
QUOTE
Please group reply to prevent getting accidentally ignored and so
everyone can help and be helped. Also please bottom post.

Whoops - sorry about that - Gmail must have picked your email address
instead of the list when I hit the reply button.


QUOTE
Though it is more of a server rather than client example. Essentially
you open the filehandles (sockets) you want to read from, add them to an
IO::Select object, then ask that object for a list of handles ready to
be read from. Then just read from the handle. On the same token you
should really be using IO::Socket::* instead of messing with the sockets
directly.

Aha - I must have confused it with some other select - I thought
select() just selected which socket is the default.

QUOTE
If it is good enough for Mr. Stein, it is good enough for
*almost* all of us.

Mr Stein?

QUOTE
On the same token you
should really be using IO::Socket::* instead of messing with the sockets
directly.

Umm... I am using IO::Socket::INET

QUOTE
Having said all of this, it still isn't truly multitasking because you
can still block on a socket that had a lot of data or a slow socket.
This method presumes that your CPU and IO handler is fast enough to
prevent the appearance of a slow down because of blocking.

Well, I wasn't really worried about slowdowns, but a blocking socket
would be a real problem with my application - One channel could be
sending lots and lots of messages, which wouldn't be relayed because
the program is busy blocking on the other socket.

QUOTE
perldoc -f select

Good luck,

Thanks - I just looked at the website you pointed to - it looks
perfect for what I need. The server code example is amazingly clean,
simple and elegent - I will certainly use this for all multi-socket
apps in future



--

Dave
All us base are belong to you.

Wiggins d'Anconia
[Email Removed] wrote:
QUOTE
Uhhh....  I can't believe I just posted it non-list again.  Here it is
for the list:


:-)

QUOTE
On 7/8/05, Wiggins d'Anconia <[Email Removed]> wrote:

Please group reply to prevent getting accidentally ignored and so
everyone can help and be helped. Also please bottom post.


Whoops - sorry about that - Gmail must have picked your email address
instead of the list when I hit the reply button.



Though it is more of a server rather than client example. Essentially
you open the filehandles (sockets) you want to read from, add them to an
IO::Select object, then ask that object for a list of handles ready to
be read from. Then just read from the handle. On the same token you
should really be using IO::Socket::* instead of messing with the sockets
directly.


Aha - I must have confused it with some other select - I thought
select() just selected which  socket is the default.


Just a comment for the archives, and to any other beginner to the Perl
docs. Some functions in Perl act differently in different situations,
depending either on context or surrounding code. C<select> is a perfect
example. When you look at the perldoc for select, perldoc -f select, you
will see that there are two distinct sections and ways to write a call
to select. Indicated by:

select FILEHANDLE
select

.....

select RBITS,WBITS,EBITS,TIMEOUT

.....

So in this particular case there is what is known as the 1 argument form
and the 4 argument form of select. The first version is the commonly
used form that returns (and optionally sets) the current default
filehandle. Shown as either plain 'select' with no argument (whereby I
suspect perl really looks at this as 1 argument where the default
filehandle is used) or select with a filehandle. The second version,
the 4 argument form, is infrequently used (relatively) and calls the
select system call. For the details read the man pages...

My point is that when reading the perl documentation you need to pay
particular attention to the "header" or "syntax annotation" to
understand the context in which the function, et al, can and should be
used. Three other important examples include C<map>, C<grep>, and C<eval>.

perldoc -f map
perldoc -f grep
perldoc -f eval

Notice for the first two the difference between 'map/grep BLOCK' and
'map/grep EXPR', especially note the comma in the second. There are a
number of other examples, but hopefully you get the idea.

QUOTE

If it is good enough for Mr. Stein, it is good enough for
*almost* all of us.


Mr Stein?


He is author/maintainer of *just* a couple of the frequently used CPAN
modules, you know like CGI.pm ;-). Major contributor to the bioperl
efforts, wrote Network Programming with Perl as well as co-authored
Writing Apache Modules with Perl, among others.

http://stein.cshl.org/~lstein/

QUOTE

On the same token you
should really be using IO::Socket::* instead of messing with the sockets
directly.


Umm...  I am using IO::Socket::INET


Good! I just meant avoid using the "Low-level socket functions"
directly... perldoc perlfunc.

QUOTE

Having said all of this, it still isn't truly multitasking because you
can still block on a socket that had a lot of data or a slow socket.
This method presumes that your CPU and IO handler is fast enough to
prevent the appearance of a slow down because of blocking.


Well, I wasn't really worried about slowdowns, but a blocking socket
would be a real problem with my application - One channel could be
sending lots and lots of messages, which wouldn't be relayed because
the program is busy blocking on the other socket.


Right... which is where select comes in, in whatever form you choose to
use it.

QUOTE

perldoc -f select

Good luck,


Thanks - I just looked at the website you pointed to - it looks
perfect for what I need.  The server code example is amazingly clean,
simple and elegent - I will certainly use this for all multi-socket
apps in future


Glad to hear it makes sense and should fit the bill. It will certainly
save your hair, assuming you started with any :-)....

http://danconia.org


PHP Help | Linux Help | Web Hosting | Reseller Hosting | SSL Hosting
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2005 Invision Power Services, Inc.