IO::Socket Stop listening for new connections after initial connection

S

sgt_b2002

Writing a small server where I want the server to stop accepting new
connections after the inital client connects. I'm creating the socket
as such:
$sock = new IO::Socket::INET(
LocalHost => $cip,
LocalPort => $cport,
Proto => 'tcp',
Listen => 0,
ReuseAddr => 1,
);
($csock, $c_addr) = $sock->accept();
($c_port, $c_ip) =
sockaddr_in($c_addr);
$c_ipnum = inet_ntoa($c_ip);
print "Client connecting from:
$c_ipnum:$c_port\n";

Once $csock gets defined (client connection), I would like the server
to stop listening for new connections. If I use close on the original
$sock it closes $csock as well so I'm not quite sure how to go about
achieving this. I'm pretty new to socket programming in Perl, so any
ideas would be helpful.
Thanks!
 
X

xhoster

Writing a small server where I want the server to stop accepting new
connections after the inital client connects. I'm creating the socket
as such:
$sock = new IO::Socket::INET(
LocalHost => $cip,
LocalPort => $cport,
Proto => 'tcp',
Listen => 0,
ReuseAddr => 1,
);
($csock, $c_addr) = $sock->accept();
($c_port, $c_ip) = sockaddr_in($c_addr);
$c_ipnum = inet_ntoa($c_ip);
print "Client connecting from: $c_ipnum:$c_port\n";

Once $csock gets defined (client connection), I would like the server
to stop listening for new connections. If I use close on the original
$sock

Your code does not show you using close on the original $sock.
it closes $csock as well so I'm not quite sure how to go about
achieving this.

I cannot verify this. I close $sock, and $csock goes merrily on its way,
just as I expected it to do.

Can you provide a complete, runnable program which reproduces your problem?

use IO::Socket::INET;
$sock = new IO::Socket::INET( LocalPort => 9999, Listen=> 0, ReuseAddr=> 1,
); ($csock, $c_addr) = $sock->accept();
($c_port, $c_ip) = sockaddr_in($c_addr);
$c_ipnum = inet_ntoa($c_ip);
print "Client connecting from: $csock $c_ipnum:$c_port\n";
close $sock or die $!;
print while <$csock>;

The first "telnet localhost 9999" I run connects, and stays connected for
as long as it wants, sending data to the server, which the server echos.

Any subsequent "telnet localhost 9999" I try to run gets a connection
refused.

Xho
 
S

sgt_b2002

Hey Xho, thanks for your reply. Thanks for the code too, nicely
illustrates how you do this. The reason I was having an issue was that
a while back when I started this project I asked this question in
#perl. Someone there told me that you *cannot* close the "original
socket". That kind of confused me as I thought you *should* be able to
do this. Thanks for making that clear.

After trying this in my code I can see that it works well, although
some other issues were created. I wrote a small program to illustrate
this issue. It essentially creates a server that listens on two ports.
Telnet to both ports and anything typed in one console will be sent
through the server and echo'd in the other console. Pretty simple. The
script works fine until I try to close the "original sockets". In the
code, when $asock is created I close $agent_sock. When $agent_sock is
closed, however, $client_sock closes as well. I'm really kind of
confused as to why this is happening. If you have the time, maybe you
can explain what it is I'm doing wrong. Essentially I want to listen on
both ports. When a connection is made on one port, I want to stop
listening on that port, but continue to listen on the other port until
a connection is created there. Then stop listening that port too.

Any advice you can give would be helpful.

Uncomment the close statements to see the problem I'm facing.

#!/usr/bin/perl

use IO::Select;
use IO::Socket;

while (1) {
$sel = IO::Select->new();

unless (defined $asock) {
$agent_sock = new IO::Socket::INET(
LocalHost => '127.0.0.1',
LocalPort => 1234,
Proto => 'tcp',
Listen => 1,
ReuseAddr => 1,
);
$sel->add($agent_sock);
}

unless (defined $csock) {
$client_sock = new IO::Socket::INET(
LocalHost => '127.0.0.1',
LocalPort => 4321,
Proto => 'tcp',
Listen => 1,
ReuseAddr => 1,
);
$sel->add($client_sock);
}

&startserver;

}

sub startserver {
while(@ready = $sel->can_read) {

foreach $fh (@ready) {
if ($fh == $agent_sock) {
($asock, $a_addr) = $agent_sock->accept();
#close $agent_sock;
($a_port, $a_ip) = sockaddr_in($a_addr);
$a_ipnum = inet_ntoa($a_ip);
print "Agent connecting from: $a_ipnum:$a_port\n";
$sel->add($asock);

} elsif ($fh == $client_sock) {
($csock, $c_addr) = $client_sock->accept();
#close $client_sock;
($c_port, $c_ip) = sockaddr_in($c_addr);
$c_ipnum = inet_ntoa($c_ip);
print "Client connecting from: $c_ipnum:$c_port\n";
$sel->add($csock);

} elsif ($fh == $asock) {

$asock->close unless defined ($buf = <$asock>);

print $csock $buf if defined $csock;

} elsif ($fh == $csock) {

$csock->close unless defined ($buf2 = <$csock>);

print $asock $buf2 if defined $asock;
}
}
}
}
 
X

xhoster

Hey Xho, thanks for your reply.

You are welcome. But please quote some context when you post follow-ups.
I had to go look up my post on google in order to see what it was I
originally suggested!


.....
The
script works fine until I try to close the "original sockets". In the
code, when $asock is created I close $agent_sock. When $agent_sock is
closed, however, $client_sock closes as well. I'm really kind of
confused as to why this is happening.

One thing is that you really should use strict; use warnings; and check
the success of your system calls. If you did that, I think the problem
would have made itself more clear to you.

....
while(@ready = $sel->can_read) {

foreach $fh (@ready) {
if ($fh == $agent_sock) {
($asock, $a_addr) = $agent_sock->accept();
close $agent_sock;

Here is the root cause of the problem. You are closing $agent_sock, but
then leaving it in the watch list for the IO::Select object.

You want to do:

$sel->remove($agent_sock);
close $agent_sock;

(And similar for the $client_sock code.)

(and probably the other two handles as well.)



Xho
 
S

sgt_b2002

One thing is that you really should use strict; use warnings; and check
the success of your system calls. If you did that, I think the problem
would have made itself more clear to you.

I'll be doing that from now on.
Here is the root cause of the problem. You are closing $agent_sock, but
then leaving it in the watch list for the IO::Select object.

You want to do:

$sel->remove($agent_sock);
close $agent_sock;

That did it! Soon as I added the $sel->remove for the two sockets
everything worked as it should. I should be able to incorporate this
into my project now.

I did try this initially, but did the $sel->remove *after* I closed the
socket.

close $agent_sock;
$sel->remove($agent_sock);

That caused the test program to break (input would not echo to the
other console). I'm guessing using strict, warnings, and checking
system call success would tell me why. Placing the $sel-remove *before*
I close the socket, as you suggest, works.

Thank you so much for your help, I really do appreciate it. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top