Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

TCP Server using fork to accept multiple requests

by Lucas Rey (Sexton)
on Aug 17, 2022 at 07:39 UTC ( [id://11146183]=perlquestion: print w/replies, xml ) Need Help??

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

Dear community, I'm trying to create a little server who handles multiple clients connections (at least 10). Below the current code that works perfect using fork. At least it accepts several connections from clients.

With the below code, I have the following behaviour:
- Client ask for connection ==> Accepted ==> OK
- Client sent packet ==> Received and printed ==> OK
- Client sent another packet ==> Not received ==> NOK

Most probably, the while cicle will be activated only for each connection request, so that's the reason because I cannot retrieve other packets.

Could someone help me please to adjust the below code? What I need is establish one (or more) client connection, then client send data continuosly (without disconnection) and server should reply on each packet it receives.

Thank you
Lucas

#!/usr/bin/perl -w use IO::Socket::INET; $SIG{CHLD} = sub {wait ()}; my $socket = new IO::Socket::INET ( LocalHost => '0.0.0.0', LocalPort => '5000', Proto => 'tcp', Listen => 5, Reuse => 1); die "cannot create socket $!n" unless $socket; while ($new_sock = $socket->accept()) { $pid = fork(); die "Cannot fork: $!" unless defined($pid); if ($pid == 0) { # This is the fork child $new_sock->recv(my $data, 500); print "$data\n"; } }

Replies are listed 'Best First'.
Re: TCP Server using fork to accept multiple requests
by Corion (Patriarch) on Aug 17, 2022 at 07:59 UTC

    You likely want to add an inner loop to keep on reading:

    ... if ($pid == 0) { # This is the fork child while( $new_sock->connected ) { $new_sock->recv(my $data, 500); print "$data\n"; } }
      Thank you Corion, this is working perfect!!
Re: TCP Server using fork to accept multiple requests
by tybalt89 (Monsignor) on Aug 17, 2022 at 09:22 UTC

    My preferred way of doing this (although I'd rather use an async package).

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11146183 use warnings; use IO::Socket::INET; $SIG{CHLD} = 'IGNORE'; # NOTE my $socket = new IO::Socket::INET ( LocalHost => '0.0.0.0', LocalPort => '5000', Proto => 'tcp', Listen => 5, Reuse => 1); die "cannot create socket $!n" unless $socket; while( 1 ) # NOTE because you don't want Interrupted system call to ex +it the server { if( my $new_sock = $socket->accept() ) { if( my $pid = fork() ) { # parent, nothing to do } elsif( defined $pid ) { print while <$new_sock>; # child exit; } else { die "Cannot fork: $!"; } } elsif( $! =~ /Interrupted system call/i ) { # just ignore } else { die "$! on accept call"; # some serious error } }
      # parent, nothing to do
      Um, except close the socket which is fairly important.

      Nevermind, This is perl, not C, I'm a moron.

        The socket is closed when $new_sock goes out of its scope, which is the "if" statement, so the socket IS closed when the outer "while" repeats. All the parent has to do is exit the "if".

Re: TCP Server using fork to accept multiple requests
by Anonymous Monk on Aug 17, 2022 at 09:14 UTC
    In your example, the child process keeps executing the code outside the if branch. Eventually, all your child processes spawned after a successful accept() end up waiting in another accept() call for more clients and creating more children as they connect. You should probably put an exit() at the end of the if ($pid == 0) branch.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2024-04-16 07:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found