Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   IO::Socket Stop listening for new connections after initial connection (http://www.velocityreviews.com/forums/t896084-io-socket-stop-listening-for-new-connections-after-initial-connection.html)

sgt_b2002@yahoo.com 01-13-2006 08:54 PM

IO::Socket Stop listening for new connections after initial connection
 
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!


xhoster@gmail.com 01-13-2006 11:01 PM

Re: IO::Socket Stop listening for new connections after initial connection
 
sgt_b2002@yahoo.com wrote:
> 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

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB

sgt_b2002@yahoo.com 01-19-2006 05:05 AM

Re: IO::Socket Stop listening for new connections after initial connection
 
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;
}
}
}
}


xhoster@gmail.com 01-19-2006 05:24 PM

Re: IO::Socket Stop listening for new connections after initial connection
 
sgt_b2002@yahoo.com wrote:
> 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

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB

sgt_b2002@yahoo.com 01-19-2006 06:04 PM

Re: IO::Socket Stop listening for new connections after initial connection
 
> 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. :)



All times are GMT. The time now is 01:02 PM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57