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

Alright, I have been toying around with this code seen all over the web:
#!/usr/bin/perl use IO::Socket; $SIG{CHLD} = sub {wait()}; $| = 1; $main_sock = new IO::Socket::INET( LocalHost => '192.168.x.x', LocalPort => 7800, Listen => 5, Proto => 'tcp', Reuse => 1) or die $!; while ($new_sock = $main_sock->accept()) { $pid = fork(); die "Cannot fork: $!" unless defined($pid); if ($pid == 0) { # Child process print $new_sock "Hello there, it's now ", scalar localtime, "\ +n"; while (defined ($buf = <$new_sock>)) { print "Client said: $buf"; if($buf =~ /^quit/){ close $new_sock; } } exit(0); } }
What I want, is when the word quit comes in, the daemon closes the socket for that connection, and the client hangs up. Right now, it just keeps the connection open, no matter what I do, until the client closes.

ALSO, where can I get info about what is connecting, host/ip , ect.

Replies are listed 'Best First'.
Re: Close Socket Force client to quit.
by Coruscate (Sexton) on Feb 25, 2003 at 21:34 UTC

    I just see that you've gotten an answer in the CB (add my() to the while() loop), but here's a better version of the scipt. Yes, I skip the wait() for waiting on the children. If you add it, the server will quit after the first client disconnects. :) What can I say? I like zombies :P

    #!/usr/bin/perl -w $|++; use strict; use IO::Socket; my $main_sock = new IO::Socket::INET( LocalHost => '24.71.183.153', LocalPort => 7800, Listen => 1, Proto => 'tcp', Reuse => 1 ) or die "Oops: $!"; while (my $new_sock = $main_sock->accept()) { if (my $pid = fork()) { # Parent next; } elsif (defined $pid) { # Child print $new_sock 'Hello there, it is now ', localtime, "\n"; while (defined( chomp( my $buf = <$new_sock> ) ) ) { print "Client said: $buf\n"; if ($buf =~ /^quit/) { close $new_sock; last; } } } else { die "Cannot fork: $!" unless defined($pid); } exit(0); } exit(0);


    If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, reply to this node or /msg me to tell me what is wrong with the post, so that I may update the node to the best of my ability. If you do not inform me as to why the post deserved a downvote, your vote does not have any significance and will be disregarded.

      And what of getting the host or ip of the remote host?

      Any help with that? Please?

        The ip address can be retrieved using $new_sock->peerhost().

Re: Close Socket Force client to quit.
by pg (Canon) on Feb 26, 2003 at 05:47 UTC
    I simplified some real code I have, and made it into this demo.

    One thing you may notice is that, after fork, as the best practice, in the child process, I close the parent socket; and in the parent process, I close the child socket. The purpose of this is to release resouces, as you don't want to hold anything you don't need.

    As jasonk pointed out, you can use peerhost() to get the peer ip addr in xx.xx.xx.xx (ascii) format. His way is very straight forward. Just for the sack of completeness, I provide a different way, by using inet_ntoa($client->peeraddr()). The peeraddr() function returns the peer ip in number format, inet_ntoa is then called to convert number format into ascii format.

    server.pl use IO::Socket; use strict; $| ++; my $server = new IO::Socket::INET(Timeout => 7200, Proto => "tcp", LocalPort => 3000, Reuse => 1, Listen => 2); my $num_of_client = -1; while (1) { my $client; do { $client = $server->accept; } until (defined($client)); print "new clinet accepted, id = ", ++ $num_of_client, ", peeraddr = ", inet_ntoa($client->peeraddr()), ", peerport = ", $client->peerport(), "\n"; if (!fork) { close($server);#this only closes the copy in the child process while (1) { my $msg; $client->recv($msg, 1000); if ($msg eq "") { die "child $num_of_client is inactive\n"; } else { print "rcvd $msg from client ", $num_of_client, "\n"; sleep(2); print $client $msg; } } } else { close($client); #this only closes the copy in the parent proce +ss, assume the parent no longer need talk to the client } } client.pl: use IO::Socket; use strict; my $server = new IO::Socket::INET(Proto => "tcp", PeerAddr => "localhost", PeerPort => 3000, Reuse => 1, Timeout => 7200) || die "failed to connect to server\n"; while (1) { print $server "abcd"; my $msg; $server->recv($msg, 1000); if ($msg eq "") { die "server is not responding"; } else { print "recv'd ", $msg, "\n"; } }
Re: Close Socket Force client to quit.
by Coruscate (Sexton) on Feb 25, 2003 at 21:12 UTC

    All I can say... that code runs 100% like the way you want it to. When I say 'quit' it quits. Immediately. Can you give some specifics as to what version of perl, what operating system you are on, etc etc?


    If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, reply to this node or /msg me to tell me what is wrong with the post, so that I may update the node to the best of my ability. If you do not inform me as to why the post deserved a downvote, your vote does not have any significance and will be disregarded.

      This is perl, v5.6.1 built for i386-linux