How to close a listening socket asynchronously

Discussion in 'Perl Misc' started by Franz Prilmeier, Feb 11, 2005.

  1. Hi,

    I want to write a simple SMTP server (As a side note with
    Net::SMTP::Server) for evaluating incoming mails. One of my objectives is
    having a proper server shutdown. I will try to argue on a code example:

    -- Begin Perl Code --
    #! /usr/bin/perl -w

    use strict;

    use IO::Socket;

    my $pid;
    my $socket = new IO::Socket::INET->new(LocalPort => 10025,
    Type => SOCK_STREAM,
    Reuse => 1,
    Listen => 10 )
    or die "Couldn't be a tcp server on port 10025 : $@\n";
    $| = 1;

    FORK:
    {
    $pid = fork;
    die "can't fork" unless defined $pid;

    if ( $pid )
    {
    print "Child\n";
    &run_server ( $socket );
    print "Child shutdown finished\n";
    }
    else
    {
    print "Parent\n";
    sleep 1;
    print "Parent shutdown\n";
    &stop_server ( $socket );
    print "Parent shutdown finished\n";
    exit
    }
    }

    sub run_server
    {
    my $server = shift;
    my $client;

    while ( $client = $server-> accept () )
    {
    print "Incomming connection";
    }

    close ( $server );
    }

    sub stop_server
    {
    my $server = shift;

    print "Entered Stop Server";
    close ( $server );
    }
    -- End of perl code --

    A friend of mine already told me, that $server in the child might not the
    same object as $server in the parent thread. So this code example is
    plain wrong, but I hope it helps to get you my intention:

    I want to be able to close a socket while it is listening (waiting for
    incoming connection via the accept call). In a different thread. And
    definitely not by killing the whole program. I want to be able to do this
    inside the same program. I haven't been able to find any proper solutions
    (except connecting to the socket in the stop method - which is not what I
    want to do either).

    To be short: Is there a clean way to close a socket while it is listening
    for incoming connections?

    Thanks in advance,
    Franz
    --
    Kind regards, Franz Prilmeier
    WWW: http://home.in.tum.de/~prilmeie/ E-Mail:
    GPG Public Key available at:
    http://home.in.tum.de/~prilmeie/gpg/
     
    Franz Prilmeier, Feb 11, 2005
    #1
    1. Advertising

  2. Franz Prilmeier <-muenchen.de> wrote in
    news:pine.GSO.4.60.0502112210470.20810@sunhalle89:

    > To be short: Is there a clean way to close a socket while it is
    > listening for incoming connections?



    Does

    perldoc -f shutdown

    help?

    Sinan
     
    A. Sinan Unur, Feb 11, 2005
    #2
    1. Advertising

  3. Franz Prilmeier

    Guest

    Franz Prilmeier <-muenchen.de> wrote:
    > Hi,
    >
    > I want to write a simple SMTP server (As a side note with
    > Net::SMTP::Server) for evaluating incoming mails. One of my objectives is
    > having a proper server shutdown.


    What do you mean by a "proper server shutdown"?

    > I will try to argue on a code example:


    Your code also doesn't tell us what you mean by a proper server shutdown.
    Unless you mean that shutting down your server very second is proper, which
    I highly doubt.

    ....
    >
    > A friend of mine already told me, that $server in the child might not the
    > same object as $server in the parent thread.


    I don't see why it wouldn't be. $socket was set before the fork.

    > I want to be able to close a socket while it is listening (waiting for
    > incoming connection via the accept call). In a different thread.


    Perl doesn't to threads very well.

    > And
    > definitely not by killing the whole program. I want to be able to do this
    > inside the same program.


    Upon what event?

    > I haven't been able to find any proper solutions
    > (except connecting to the socket in the stop method - which is not what I
    > want to do either).


    By calling "accept", you are declaring that want to block until something
    connects. If you don't want to block until something connects, don't
    call "accept" until/unless you know someone is knocking on the door.

    Stuff the $socket into an IO::Select object, then use can_read to see if
    there is something trying to connect to $socket. (See the example given in
    perldoc IO::Select).

    Now that you are only checking in every now and then to see if anyone is
    there, you are free to close the socket whenever you wish.

    >
    > To be short: Is there a clean way to close a socket while it is listening
    > for incoming connections?



    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Feb 12, 2005
    #3
  4. On Sat, 12 Feb 2005 wrote:

    > Franz Prilmeier <-muenchen.de> wrote:
    >> Hi,
    >>
    >> I want to write a simple SMTP server (As a side note with
    >> Net::SMTP::Server) for evaluating incoming mails. One of my objectives is
    >> having a proper server shutdown.

    >
    > What do you mean by a "proper server shutdown"?


    Stopping the server listening.

    >> I will try to argue on a code example:

    >
    > Your code also doesn't tell us what you mean by a proper server shutdown.
    > Unless you mean that shutting down your server very second is proper, which
    > I highly doubt.


    I am not a perl guru, but I am definitely a Java guru. So I hope you get
    my intention on a Java example (See below, SocketTest.java). This is the
    output of that little program:

    $ javac SocketTest.java && java SocketTest
    starting server
    Restarting Server:
    Exception in Runner: java.net.SocketException: socket closed
    starting server
    Stopping Server:
    Exception in Runner: java.net.SocketException: socket closed
    Server exiting

    That's exactly what I want to do in Perl. Stop the server listening
    while it's blocked doing an accept. Is there one way to do it?

    >> I want to be able to close a socket while it is listening (waiting for
    >> incoming connection via the accept call). In a different thread.

    >
    > Perl doesn't to threads very well.


    That would be a show stopper. I have to do that in Perl because all my
    mates just know Perl.

    >> And
    >> definitely not by killing the whole program. I want to be able to do this
    >> inside the same program.

    >
    > Upon what event?


    I have a second control connection either by keyboard input or by remote
    command.

    > By calling "accept", you are declaring that want to block until something
    > connects. If you don't want to block until something connects, don't
    > call "accept" until/unless you know someone is knocking on the door.
    >
    > Stuff the $socket into an IO::Select object, then use can_read to see if
    > there is something trying to connect to $socket. (See the example given in
    > perldoc IO::Select).


    As far as I got IO::Select, this means busy waiting to me.

    Franz

    -- Begin SocketTest.java --
    import java.net.*;

    public class SocketTest {
    public static void main ( String [] args ) throws Exception {
    ServerRunner sr = new ServerRunner ( 10025 );
    sr.start ();

    ServerStopper st = new ServerStopper ( sr );
    st.start ();
    }

    public static class ServerRunner extends Thread {
    private ServerSocket socket = null;
    private boolean shouldRun = true;
    int port;

    public ServerRunner ( int port ) throws Exception {
    this.port = port;
    }

    public void run () {
    while ( this.shouldRun ) {
    Socket s = null;

    try {
    System.out.println ( "starting server" );
    this.socket = new ServerSocket ( port );

    while ( this.shouldRun ) {
    s = this.socket.accept ();
    System.out.println ( "Got a connection" );
    s.close ();
    }
    } catch ( Exception e ) {
    System.out.println ( "Exception in Runner: " + e );
    } finally {
    try {
    if ( s != null ) s.close ();
    } catch ( Exception e ) { /* Discard */ }
    }
    }

    try {
    this.socket.close ();
    } catch ( Exception e ) {
    System.out.println (
    "Exception in Runner during Socket close " + e );
    }

    System.out.println ( "Server exiting" );
    }

    public ServerSocket getServer () {
    return this.socket;
    }

    public void halt () {
    this.shouldRun = false;
    }
    }

    public static class ServerStopper extends Thread {
    private ServerRunner server;

    public ServerStopper ( ServerRunner sr ) {
    this.server = sr;
    }

    public void run () {
    try {
    super.sleep ( 1000 );
    System.out.println ( "Restarting Server:" );
    this.server.getServer ().close ();

    super.sleep ( 1000 );
    System.out.println ( "Stopping Server:" );
    this.server.halt ();
    this.server.getServer ().close ();
    } catch ( Exception e ) {
    System.out.println ( "Exception in Stopper: " + e );
    }
    }
    }
    }
    -- End of SocketTest.java --


    --
    Kind regards, Franz Prilmeier
    WWW: http://home.in.tum.de/~prilmeie/ E-Mail:
    GPG Public Key available at:
    http://home.in.tum.de/~prilmeie/gpg/
     
    Franz Prilmeier, Feb 12, 2005
    #4
  5. Franz Prilmeier

    Big and Blue Guest

    Franz Prilmeier wrote:

    >>> I want to be able to close a socket while it is listening (waiting for
    >>> incoming connection via the accept call). In a different thread.

    >>


    A suggestion (there are other ways as well...)

    Get the other thread to open a call on the socket and send a "shutdown"
    command. For security (to stop anyone connecting to the socket and
    shuting it down) create a random string in the program, get this thread to
    send it and the listener can check it.

    --
    Just because I've written it doesn't mean that
    either you or I have to believe it.
     
    Big and Blue, Feb 13, 2005
    #5
  6. On Sun, 13 Feb 2005, Big and Blue wrote:

    > Franz Prilmeier wrote:
    >
    >>>> I want to be able to close a socket while it is listening (waiting for
    >>>> incoming connection via the accept call). In a different thread.
    >>>

    >
    > A suggestion (there are other ways as well...)
    >
    > Get the other thread to open a call on the socket and send a "shutdown"
    > command. For security (to stop anyone connecting to the socket and shuting
    > it down) create a random string in the program, get this thread to send it
    > and the listener can check it.


    That would be a possible solution, and also one I thought of. Security is
    no issue here, because the server is intended to be run for test purposes
    only, not in a production environment (Or even on the internet). My
    problem with this solution is, that it smells bad to me. It's a hack, and
    I want to avoid hacks in my programs whenever possible.

    I would like to try one of the other ways, preferable the one I showed in
    the Java example. Is there are Perl equivalent?

    Franz
    --
    Kind regards, Franz Prilmeier
    WWW: http://home.in.tum.de/~prilmeie/ E-Mail:
    GPG Public Key available at:
    http://home.in.tum.de/~prilmeie/gpg/
     
    Franz Prilmeier, Feb 13, 2005
    #6
  7. Franz Prilmeier

    Guest

    Franz Prilmeier <-muenchen.de> wrote:
    >
    > That's exactly what I want to do in Perl. Stop the server listening
    > while it's blocked doing an accept. Is there one way to do it?


    As a previous poster suggested, using "shutdown" rather than "close" on the
    socket seems to work for that. If your goal is simply to get your test
    code to work, that would probably be the way to go. But presumably your
    test code is a test for some other ultimate goal, and just getting this
    test code to work may not be very effective at helping you attain that
    ultimate goal.

    > >> I want to be able to close a socket while it is listening (waiting for
    > >> incoming connection via the accept call). In a different thread.

    > >
    > > Perl doesn't to threads very well.

    >
    > That would be a show stopper. I have to do that in Perl because all my
    > mates just know Perl.


    It may be easier to teach your mates Java than to kludge around Perl's
    threading model. You may want to look into the various ways to meld
    Perl and Java, so that you get the best of both worlds.

    >
    > >> And
    > >> definitely not by killing the whole program. I want to be able to do
    > >> this inside the same program.

    > >
    > > Upon what event?

    >
    > I have a second control connection either by keyboard input or by remote
    > command.


    If "by keyboard" means the signals sent when you hit ctrl-C, then you will
    want to look into SIG handlers. For remote commands, just treat those
    commands as one more thing to be waited for.

    >
    > > By calling "accept", you are declaring that want to block until
    > > something connects. If you don't want to block until something
    > > connects, don't call "accept" until/unless you know someone is knocking
    > > on the door.
    > >
    > > Stuff the $socket into an IO::Select object, then use can_read to see
    > > if there is something trying to connect to $socket. (See the example
    > > given in perldoc IO::Select).

    >
    > As far as I got IO::Select, this means busy waiting to me.


    Only if you program it that way. Stuff both the listener (e.g. $socket)
    and whatever is going to send you the "stop listening" command into the
    IO::Select object. Then you can call can_read without a timeout, and it
    will not busy wait, it will block until one of the two things (a new
    connection, or a shutdown command) happens.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Feb 14, 2005
    #7
    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:
    445
    Christian von Essen
    Jun 21, 2004
  2. pwilkins
    Replies:
    7
    Views:
    481
    Grant Edwards
    Jun 25, 2005
  3. Giovanni Tumiati
    Replies:
    2
    Views:
    348
    Grant Edwards
    Jun 25, 2005
  4. Jp Calderone
    Replies:
    1
    Views:
    356
    Grant Edwards
    Jun 25, 2005
  5. Iñaki Baz Castillo
    Replies:
    7
    Views:
    940
    Iñaki Baz Castillo
    Jan 12, 2010
Loading...

Share This Page