On Jan 16, 11:50 am, [EMAIL PROTECTED] (Zentara) wrote:
> On Tue, 15 Jan 2008 19:18:02 -0800 (PST), [EMAIL PROTECTED]
>
>
>
> (Turner) wrote:
> >On Jan 15, 9:23 am, [EMAIL PROTECTED] (Zentara) wrote:
> >> On Mon, 14 Jan 2008 20:26:05 -0800 (PST), [EMAIL PROTECTED]
>
> >> >> If you just want to handle multiple clients, you may want to look at the
> >> >> select() function.
> >> >> (See the bottom part in the perldoc-umentation. The one with RBITS,
> >> >> WBITS, ... or herehttp://www.perlfect.com/articles/select.shtml)
>
> >> >Thank you, that was exactly what I needed. It works beautifully now.
> >> >Thanks.
>
> >> Hi, would you mind posting the complete working code?
> >> I would like to test it
> >> for good functionality and no memory leaks with repeated
> >> connects/disconnects.
>
> >> Thanks, zentara
> >I would normally happily do so, but this program is part of an
> >application to a programming job, so I'm being cautious as to how much
> >and what kind of help I get, and I think posting it here for you to
> >debug would be kind of cheating. But I really appreciate the offer,
> >and in other circumstances, I'd certainly oblige.
>
> >However, I think general questions are legit. And with that in mind, I
> >have some questions about IO::Select. While my server runs as it
> >should, it eats up a ton of CPU cycles; when it's running, my computer
> >slows noticably. Windows Task Manager shows it taking about 50% of the
> >CPU. This is obscene. I'm pretty sure it shouldn't have that big a
> >footprint. I've done some cursory profiling with -d:DProf and the
> >problem seems to center around IO::Select::select--in one run of about
> >a minute or so, there were 280395 calls to IO::Select::select. I think
> >this is probably where most of the performance pit is. Any ideas on
> >how to fix it?
> >Thanks,
> >Turner
>
> Well, that is why I asked to see the code. It seemed suspicious that it
> worked beautifully. :-)
>
> The thing that didn't seem to jive (I use linux, so windows may act
> differently), is using IO::Select with threads.
>
> Generally, IO::Select is NOT compatible with using threads. IO:Select
> is usually used instead of threads.
>
> Typically, an IO::Select server, is preferred, because it handles
> multiple connects/disconnects very well. BUT it has a drawback,
> select can only handle one filehandle at a time. So for short chat
> messages, it works fine, and can handle alot of connections efficiently.
>
> The problem comes when you want to upload big files. Select will block
> all other clients while the big upload occurs.  In those big-file cases,
> you need to fork off to handle the client, and is called a
> forking-chat-server.
> Alternatively, to forking, you can spawn threads to handle each client.
> Using threads, would typically not require Select. The thread would be
> handed the client socket filehandle, and you can just use IO::Socket
> commands to read or write to it.
>
> This is just basiccally tested, but shows the idea of not needing
> IO::Select when using threads.
>
> #!/usr/bin/perl
> use warnings;
> use strict;
> use IO::Socket;
> use threads;
>
> $|++;
>
> my $server = new IO::Socket::INET(
>     Timeout   => 7200,
>     Proto     => "tcp",
>     LocalPort => 12345,
>     Reuse     => 1,
>     Listen    => 2
> );
> my $num_of_client = -1;
>
> while (1) {
>     my $client;
>
>     do {
>         $client = $server->accept;
>     } until ( defined($client) );
>
>     my $peerhost = $client->peerhost();
>     print "accepted a client $client, $peerhost, id = ",
> ++$num_of_client, "\n";
>
>      #spawn  a thread here for each client
>    my $thr = threads->new( \&processit,$client,$peerhost )->detach();
>
> }
>
> sub processit {
>      my ($lclient,$lpeer) = @_; #local client
>
>      if($lclient->connected){
>           # Here you can do your stuff
>           # I use have the server talk to the client
>           # via print $client and while(<$lclient>)
>           print $lclient "$lpeer->Welcome to server\n"; #and
>           while(<$lclient>){print $lclient "$lpeer->$_\n"}
>
>     }
>
>   #close filehandle before detached thread dies out
>   close( $lclient);}
>
> )
>
> __END__
>
> Of course there are ALL sorts of missing details. Like do you want
> a "multi-echo chat server" where all clients gets messages from all
> clients?  If so, it is more difficult with threads, you will need some
> shared array to keep all socket filehandles in. How to kill a thread
> prematurely? etc. etc.
>
> The most time tested, and best working chat servers are those
> that fork and use IO::Select. BUT windows emulates fork with threads,
> so I can't say whether you are better off on windows, directly using
> threads.
>
> But the above is the basic idea for threads.
>
> zentara
>
> --
> I'm not really a human, but I play one on earth.http://zentara.net/japh.html

I think you may have misunderstood me. I'm now using exclusively
IO::Select--I dumped threads entirely (it's not you, threads, it's
me). I don't use fork either, now--just IO::Select. I got the
impression that fork would be kind of redundant with IO::Select.
Here's a snippet of my IO::Select code:


Code:
=================================================================

sub start {
        use IO::Socket;

        my ($self) = @_;

        my $host = $self->{'host'};
        my $port = $self->{'port'};

        my $sock = new IO::Socket::INET(
                           LocalHost => $host,
                           LocalPort => $port,
                           Proto     => 'tcp',
                           Listen    => SOMAXCONN,
                           Reuse     => 1);

        use IO::Select;

        my $select_set = new IO::Select();
        $select_set->add($sock);        #Add listening socket to select


        while(1) {
                my ($readables) = IO::Select->select($select_set, undef, undef, 
0);

                foreach my $r (@$readables) {
                        if($r == $sock) {
                                my ($new_sock, $client_addr) = $r->accept();
                                $select_set->add($new_sock);
                                ...process new socket...
                        }
                        else {
                                if(defined(my $buf = <$r>)) {
                                        ..process $buf..
                                }
                                #Client closed connection
                                else {
                                        $select_set->remove($r);
                                        close($r);
                                }
                        }
                }
        }
}

===================================================================

I basically took that straight from the tutorial Robert Leibl linked
me to here. It handles mutiple (well, two) clients appropriately--
everything works as it should, just with a lot more CPU usage than it
should


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to