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

Discussion in 'Perl Misc' started by sgt_b2002@yahoo.com, Jan 13, 2006.

  1. Guest

    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!
    , Jan 13, 2006
    #1
    1. Advertising

  2. Guest

    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
    , Jan 13, 2006
    #2
    1. Advertising

  3. Guest

    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;
    }
    }
    }
    }
    , Jan 19, 2006
    #3
  4. Guest

    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
    , Jan 19, 2006
    #4
  5. Guest

    > 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. :)
    , Jan 19, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christian von Essen

    Listening socket not seen outside of localhost

    Christian von Essen, Jun 21, 2004, in forum: Python
    Replies:
    2
    Views:
    413
    Christian von Essen
    Jun 21, 2004
  2. Helene Unterwieser
    Replies:
    14
    Views:
    3,645
    Esmond Pitt
    Jul 3, 2007
  3. Rick van Hattem
    Replies:
    2
    Views:
    432
    Rick van Hattem
    Dec 26, 2008
  4. Igor Katson
    Replies:
    11
    Views:
    19,372
    Lawrence D'Oliveiro
    May 31, 2009
  5. Igor Katson
    Replies:
    0
    Views:
    384
    Igor Katson
    May 24, 2009
Loading...

Share This Page