Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

request, IO::Socket Select() & Fork() example

by Treehunter (Beadle)
on Mar 06, 2005 at 04:23 UTC ( #436988=perlquestion: print w/replies, xml ) Need Help??
Treehunter has asked for the wisdom of the Perl Monks concerning the following question:

I have been looking into using sockets with Perl because I really want to learn as much as I can about perl. Currently I'm attempting to learn sockets. I have the basics of IO::Socket down. Now to get multipul client's to connect from what I understand requires eather IO::Select; or fork(); apparently fork eats up processor though. Eather way I have copied example scripts and always end up with the same issue. They don't print any of the data that I send to them. If some one could give me a link to a very well explained IO::Socket with IO::Select or forking and or write a script with very well explained comments it would be appriciated. I apologize for not posting what I have tried in the past, generally when I go looking for examples and tutorials it's not at home. Mainly in class when I'm doing nothing important I tend to look up information on perl. Then I end up deleting the examples in frustration or never bringing them home. Thank your for the Links I'll give them a try.
  • Comment on request, IO::Socket Select() & Fork() example

Replies are listed 'Best First'.
Re: request, IO::Socket Select() & Fork() example
by zentara (Archbishop) on Mar 06, 2005 at 11:35 UTC
    Here are some snippets to play with. The first is a general purpose client, which should connect to all the servers. These all work on my localhost.
    #client############################## #!/usr/bin/perl -w use strict; use IO::Socket; my ( $host, $port, $kidpid, $handle, $line ); ( $host, $port ) = ('',1200); my $name = shift || ''; if($name eq ''){print "What's your name?\n"} chomp ($name = <>); # create a tcp connection to the specified host and port $handle = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $host, PeerPort => $port ) or die "can't connect to port $port on $host: $!"; $handle->autoflush(1); # so output gets there right away print STDERR "[Connected to $host:$port]\n"; # split the program into two processes, identical twins die "can't fork: $!" unless defined( $kidpid = fork() ); # the if{} block runs only in the parent process if ($kidpid) { # copy the socket to standard output while ( defined( $line = <$handle> ) ) { print STDOUT $line; } kill( "TERM", $kidpid ); # send SIGTERM to child } # the else{} block runs only in the child process else { # copy standard input to the socket while ( defined( $line = <STDIN> ) ) { print $handle "$name->$line"; } }

    And now some servers. First a very basic one...forking and using IO::Socket

    #!/usr/bin/perl #This is a version that can read and write #from as many clients as your machine supports. use strict; use warnings; use IO::Socket; my $server = IO::Socket::INET->new ( LocalAddr => '', LocalPort => 1200, Type => SOCK_STREAM, Reuse => 1, Listen => 5 ) or die "could not open port\n"; warn "server ready waiting for connections..... \n"; my $client; while ($client = $server->accept()) { my $pid; while (not defined ($pid = fork())) { sleep 5; } if ($pid) { close $client; # Only meaningful in the client } else { $client->autoflush(1); # Always a good idea close $server; &do_your_stuff(); } } sub do_your_stuff { warn "client connected to pid $$\n"; while(my $line = <$client>) { print "client> ", $line; print $client "pid $$ > ", $line; } exit 0; }

    And now IO::Select with IO::Socket

    #!/usr/bin/perl use IO::Socket; use IO::Select; my @sockets; my $machine_addr = ''; $main_sock = new IO::Socket::INET(LocalAddr=>$machine_addr, LocalPort=>1200, Proto=>'tcp', Listen=>3, Reuse=>1, ); die "Could not connect: $!" unless $main_sock; print "Starting Server\n"; $readable_handles = new IO::Select(); $readable_handles->add($main_sock); while (1) { ($new_readable) = IO::Select->select($readable_handles, undef, undef +, 0); foreach $sock (@$new_readable) { if ($sock == $main_sock) { $new_sock = $sock->accept(); $readable_handles->add($new_sock); } else { $buf = <$sock>; if ($buf) { print "$buf\n"; my @sockets = $readable_handles->can_write(); #print $sock "You sent $buf\n"; foreach my $sck(@sockets){print $sck "$buf\n";} } else { $readable_handles->remove($sock); close($sock); } } } } print "Terminating Server\n"; close $main_sock; getc();

    Here is a super simple one using Socket

    #!/usr/bin/perl use strict; use warnings; use Socket; my $proto = getprotobyname('tcp'); my $port = 1200; # Create 'sockaddr_in' structure to listen to the given port # on any locally available IP address my $servaddr = sockaddr_in($port, INADDR_ANY); # Create a socket for listening on socket SERVER, PF_INET, SOCK_STREAM, $proto or die "Unable to create socket: $!"; # bind the socket to the local port and address bind SERVER, $servaddr or die "Unable to bind: $!"; # listen to the socket to allow it to receive connection requests # allow up to 10 requests to queue up at once. listen SERVER, 10; # now accept connections print "Server running on port $port...\n"; while (accept CONNECTION, SERVER) { select CONNECTION; $| = 1; print STDOUT "Client connected at ", scalar(localtime), "\n"; print CONNECTION "You're connected to the server!\n"; while (<CONNECTION>) { print STDOUT "Client says: $_\n"; print CONNECTION "You said $_\n"; } close CONNECTION; print STDOUT "Client disconnected\n"; }

    The thing to remember, when trying to decide whether to use a forking(or threaded) server, versus IO::Select, is how much time each transmission will take. If you are uploading or downloading files, (or something big ), servers based on IO::Select, will block the other clients, while the file transfer occurs. So you probably want a forking server.

    If the transmissions are short, then IO:Select is probably better.

    For a really good explanation of basic servers, with heavily commented perl code, go to Golden-UNO and look for the section "Perl".

    Also check out Net::EasyTCP, which is a nice way to do IO::Select'ed servers, since it incorporates "port passwords", "encryption", and passing "perl hashes" through the sockets.

    I'm not really a human, but I play one on earth. flash japh
Re: request, IO::Socket Select() & Fork() example
by Zaxo (Archbishop) on Mar 06, 2005 at 04:48 UTC

    The performance of fork is system-dependent. Linux provides a very inexpensive fork, the task generation and switch being faster than threads due to Copy On Write for the environment and other optimizations. Windows perl emulates fork with win32 native threads which I believe to be rather expensive.

    IO::Select is a wrapper for perl's 4-arg select. It is, in effect, a sleep-until-I/O-ready operation.

    You don't say what examples you have tried, but "They don't print any of the data that I send to them" sounds like you have problems with either buffering or making the connection from a client. Or maybe just the printing. You need to show code to get a diagnosis from us.

    It's de rigeur to recommend POE at this point, but I'm not going to do that yet. It's worthwhile to learn to use bare metal sockets and fork.

    After Compline,

Re: request, IO::Socket Select() & Fork() example
by Tanktalus (Canon) on Mar 06, 2005 at 04:28 UTC

    I did notice that the other response to your second question (ever) here on PM, Question about IO::Socket, used IO::Select. Did you have additional comments there? Also, if you could show what you've tried so far, and what behaviour you got vs what behaviour you expected, we could go a long way towards helping.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://436988]
Approved by Tanktalus
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (8)
As of 2018-11-20 15:40 GMT
Find Nodes?
    Voting Booth?
    My code is most likely broken because:

    Results (227 votes). Check out past polls.