Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Activeperl 5.6 fork() doesn't friggin work

by jtx (Initiate)
on Apr 18, 2002 at 00:25 UTC ( [id://160058]=perlquestion: print w/replies, xml ) Need Help??

jtx has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to create a simple client/server using IO::Socket, and well, under Linux everything runs just fine. However, my boss, being a... boss, has decided he wants me to write a Win32 client for him (ugh, what a nightmare this is going to be). Anyhow, my first problem with getting my client to work is that fork() doesn't seem to work properly on Win32 with ActivePerl 5.6.1.631 (Latest Build as far as I can tell. It's really bothering me, as everywhere I look everyone says 'fork() works fine in 5.6... etc'. Basically, through sockets, I'm doing a simple 'Client send server data. Server look at data, send response back to client', and they do this until one or the other decides it's time to close the socket. Here's my code for the client which works just great under linux. Any help in rewriting this thing would be greatly greatly appreciated:
#!/usr/bin/perl use IO::Socket; # Make our connections my $ns1 = new IO::Socket::INET (PeerAddr => shell, PeerPort => 1200, Proto => 'tcp' ) or die "Couldn't create socket: $!\n" +; # Now let's fork the client so we can read and write my $pid = fork(); $fork_errlvl = 1 unless defined $pid; # If we weren't able to fork... die "Error forking client: Reason: $!\n" if $fork_errlvl != 0; if ($pid) { write_sock(); waitpid($pid, 0); } else { read_sock(); } sub write_sock { foreach my $key (@ARGV) { print $ns1 "$key\n"; sleep(1); } close($ns1); } sub read_sock { while (my $line = <$ns1>) { chomp($line); print "$line\n"; if ($line eq 'CAIO') { close($ns1); } } }

Replies are listed 'Best First'.
Re: Activeperl 5.6 fork() doesn't friggin work
by tachyon (Chancellor) on Apr 18, 2002 at 00:45 UTC

    fork() is flaky on Win32 in my experience but you can get it to do some things. For a start I would try setting autoflush with a $|++ Also from the docs:

    NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE As of VERSION 1.18 all IO::Socket objects have autoflush turned o +n by default. This was not the case with earlier releases. NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE

    If you have working code on Linux it could be related to an outdated version of IO::Socket on the Windows box. merlyn will have a column on this and I know he has written a number of client/server apps. Check out his home node.

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Activeperl 5.6 fork() doesn't friggin work
by premchai21 (Curate) on Apr 18, 2002 at 00:34 UTC

    Are you sure you need fork for this? Why not just do something like:

    #!/usr/bin/perl # Pseudo-Perl; some code shortened to ellipses or text. use IO::Socket; my $sock = IO::Socket::INET->new(...) or die "..."; while (not yet done) # Not sure how you want to determine this { my $line; print $sock "send this to server\n"; chomp($line = <$sock>); #<process $line (one line read from server's response)> } __END__

    Also note that

    $fork_errlvl = 1 unless defined $pid; die "Error forking client: Reason: $!\n" if $fork_errlvl != 0;

    can be shortened to

    die "..." unless defined $pid;

    or, better IMHO,

    defined($pid) or die "..."

    both of which eliminate the unnecessary variable.

      This code does work, but it's assuming the client has to write to the server, and then the server replies. While this is generally the case, it's ALSO possible for the server to write to the client without first receiving any information. For example, the client could send the server "data:foo", then the server responds "received". If that was all the information the server needed to complete the operation, it would then respond saying whether the task completed successfully or not. The reason I was forking is so that I have a persistant child listening for whatever the server said.

        Ah. I gathered from your original post (assuming you are jtx) that it was always client, server in strict alternation. If that's not the case, you might be able to use select to determine whether there is data waiting to be read. I believe POE can do this sort of stuff relatively easily, though it may well be overkill.

Re: Activeperl 5.6 fork() doesn't friggin work
by Corion (Patriarch) on Apr 18, 2002 at 07:04 UTC

    I'd say that fork() does work sometimes under ActiveState Perl, but the problems start as soon as you share too much stuff (like, for example, sockets) between the two processes.

    There are some ways around your specific problem, for example, you could use a perlfunc:select-based client that checks whether there is something to read or write. I've done so with a server here, but the concept can be reused for a client as well.

    As for another route, if you have control over the server as well, you might want to change your protocol to HTTP or some other protocol that sends the size of the response within the response header.

    perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://160058]
Approved by premchai21
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-19 07:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found