client server socket interaction (inetd)

Discussion in 'Python' started by Tim, Feb 17, 2011.

  1. Tim

    Tim Guest

    Hi, I have an inetd service on freebsd that calls a program
    (daemon.py) with which I want the remote user to communicate. I can
    call daemon.py from the command line on the host machine and it works
    fine.

    What I don't understand is how to make my remote client script
    actually communicate. If I'm understanding correctly, the code below
    just takes a message and sends it to inetd and writes the stdout from
    the process to the client.

    How can I modify the code to send a response back? Here's the
    outline of what I want to do:
    (1) client sends the message to the server (client -> inetd ->
    daemon.py),
    (2) client receives output back from the server,
    (3) client user responds to a question from the remote process
    (4) client continues to receive output back.

    where 2-3-4 happen as needed by the remote process. Cries out for a
    while loop doesn't it? I just don't know what to put in it. Currently
    I just have steps 1 and 2 working. Client sends one message and gets
    all output back. If server asks a question, processes deadlock with
    server waiting and client unable to respond.
    thanks,
    --Tim Arnold

    # imports, constants set
    #def line_buffer(sock):
    # code to yield the string response in
    # blocks of 1024 bytes

    def client(ip,port,message):
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sock.connect((ip,port))
    sock.send(message)
    for line in line_buffer(sock):
    print line
    sock.close()

    if __name__ == '__main__':
    message = ' '.join(sys.argv[1:]) )
    print 'working... %s %s' % (SERVER_IP,SERVER_PORT)
    client(SERVER_IP,SERVER_PORT,message)
    print 'done.'
     
    Tim, Feb 17, 2011
    #1
    1. Advertising

  2. On Thu, 17 Feb 2011 08:14:36 -0800, Tim wrote:

    > Hi, I have an inetd service on freebsd that calls a program (daemon.py)
    > with which I want the remote user to communicate. I can call daemon.py
    > from the command line on the host machine and it works fine.
    >
    > What I don't understand is how to make my remote client script actually
    > communicate. If I'm understanding correctly, the code below just takes a
    > message and sends it to inetd and writes the stdout from the process to
    > the client.
    >
    > How can I modify the code to send a response back?
    >

    The code you've shown would appear to be doing what you've specified,
    though only you can know whether this is what you intended.
    Each time you run the client it:
    - connects to the server
    - sends a request
    - reads the response(s)
    - closes the socket and exits.

    If you run it a second time it should do the same again. Is this the case?

    An inetd server should be started when a connection request is received.
    It should read requests, sending a response to each request in turn,
    until the connection is closed, when it will be stopped by inetd.

    Without seeing the code for the server and the corresponding inetd
    configuration line its not possible to say more.

    BTW, I prefer xinetd to inetd - its configuration is much more modular
    and easier to understand. If freebsd supports xinetd it may make life
    easier if you use it rather than inetd.



    Here's the outline
    > of what I want to do:
    > (1) client sends the message to the server (client -> inetd ->
    > daemon.py),
    > (2) client receives output back from the server, (3) client user
    > responds to a question from the remote process (4) client continues to
    > receive output back.
    >
    > where 2-3-4 happen as needed by the remote process. Cries out for a
    > while loop doesn't it? I just don't know what to put in it. Currently I
    > just have steps 1 and 2 working. Client sends one message and gets all
    > output back. If server asks a question, processes deadlock with server
    > waiting and client unable to respond. thanks,
    > --Tim Arnold
    >
    > # imports, constants set
    > #def line_buffer(sock):
    > # code to yield the string response in # blocks of 1024 bytes
    >
    > def client(ip,port,message):
    > sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    > sock.connect((ip,port))
    > sock.send(message)
    > for line in line_buffer(sock):
    > print line
    > sock.close()
    >
    > if __name__ == '__main__':
    > message = ' '.join(sys.argv[1:]) )
    > print 'working... %s %s' % (SERVER_IP,SERVER_PORT)
    > client(SERVER_IP,SERVER_PORT,message) print 'done.'




    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
     
    Martin Gregorie, Feb 17, 2011
    #2
    1. Advertising

  3. Re: client server socket interaction (inetd)

    On Feb 17, 2:41 pm, Martin Gregorie <>
    wrote:
    > On Thu, 17 Feb 2011 08:14:36 -0800, Tim wrote:
    > > Hi, I have an inetd service on freebsd that calls a program (daemon.py)
    > > with which I want the remote user to communicate. I can call daemon.py
    > > from the command line on the host machine and it works fine.

    >
    > > What I don't understand is how to make my remote client script actually
    > > communicate. If I'm understanding correctly, the code below just takes a
    > > message and sends it to inetd and writes the stdout from the process to
    > > the client.

    >
    > > How can I modify the code to send a response back?

    >
    > The code you've shown would appear to be doing what you've specified,
    > though only you can know whether this is what you intended.
    > Each time you run the client it:
    > - connects to the server
    > - sends a request
    > - reads the response(s)
    > - closes the socket and exits.
    >
    > If you run it a second time it should do the same again. Is this the case?
    >
    > An inetd server should be started when a connection request is received.
    > It should read requests, sending a response to each request in turn,
    > until the connection is closed, when it will be stopped by inetd.
    >
    > Without seeing the code for the server and the corresponding inetd
    > configuration line its not possible to say more.
    >
    > BTW, I prefer xinetd to inetd - its configuration is much more modular
    > and easier to understand. If freebsd supports xinetd it may make life
    > easier if you use it rather than inetd.
    >
    > Here's the outline
    >
    >
    >
    > > of what I want to do:
    > > (1) client sends the message to the server (client -> inetd ->
    > > daemon.py),
    > > (2) client receives output back from the server, (3) client user
    > > responds to a question from the remote process (4) client continues to
    > > receive output back.

    >
    > > where 2-3-4 happen as needed by the remote process. Cries out for a
    > > while loop doesn't it? I just don't know what to put in it. Currently I
    > > just have steps 1 and 2 working. Client sends one message and gets all
    > > output back. If server asks a question, processes deadlock with server
    > > waiting and client unable to respond. thanks,
    > > --Tim Arnold

    >
    > > # imports, constants set
    > > #def line_buffer(sock):
    > > # code to yield the string response in # blocks of 1024 bytes

    >
    > > def client(ip,port,message):
    > > sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    > > sock.connect((ip,port))
    > > sock.send(message)
    > > for line in line_buffer(sock):
    > > print line
    > > sock.close()

    >
    > > if __name__ == '__main__':
    > > message = ' '.join(sys.argv[1:]) )
    > > print 'working... %s %s' % (SERVER_IP,SERVER_PORT)
    > > client(SERVER_IP,SERVER_PORT,message) print 'done.'

    >
    > --
    > martin@ | Martin Gregorie
    > gregorie. | Essex, UK
    > org |



    Have a look at the SIMPL toolkit (http://www.icanprogram.com/06py/
    lesson1/lesson1.html). It will allow you to do exactly what you want
    without having to dive into socket programming.

    bob
     
    bobicanprogram, Feb 17, 2011
    #3
  4. Tim

    Tim Guest

    Re: client server socket interaction (inetd)

    On Feb 17, 2:41 pm, Martin Gregorie <>
    wrote:
    > On Thu, 17 Feb 2011 08:14:36 -0800, Tim wrote:
    > > Hi, I have an inetd service on freebsd that calls a program (daemon.py)
    > > with which I want the remote user to communicate.  I can call daemon.py
    > > from the command line on the host machine and it works fine.

    >
    > > What I don't understand is how to make my remote client script actually
    > > communicate. If I'm understanding correctly, the code below just takes a
    > > message and sends it to inetd and writes the stdout from the process to
    > > the client.

    >
    > > How can I modify the code to send a response back?

    >


    > --
    > martin@   | Martin Gregorie
    > gregorie. | Essex, UK
    > org       |


    Thanks Martin, you're right:

    > Each time you run the client it:
    > - connects to the server
    > - sends a request
    > - reads the response(s)
    > - closes the socket and exits.


    that is exactly what it's doing. But. The server may encounter a
    problem during the process and ask the user for more information like
    'abort/retry' or something like that.

    What my code does *not* do is allow the user to respond to such a mid-
    process question (so the server can take in that information and
    proceed with its process). The server can ask, but there's no
    mechanism for the user to respond to a question.

    > Without seeing the code for the server and the corresponding inetd
    > configuration line its not possible to say more.


    I'm not trying to be opaque, but the reason I left out the code for
    the server (daemon.py) is that it works as expected when exec'd from
    the command line. That is, the process begins, asks a question, gets
    an answer and continues.

    The inetd configuration is:
    myservice stream tcp nowait root /local/daemon.py daemon.py
     
    Tim, Feb 17, 2011
    #4
  5. Re: client server socket interaction (inetd)

    On Thu, 17 Feb 2011 13:02:08 -0800, Tim wrote:

    > But. The server may encounter a problem
    > during the process and ask the user for more information like
    > 'abort/retry' or something like that.
    >

    Servers never ask the client for information: they are strictly request/
    response handlers. To do what you're asking about, you'll need to change
    both the client and server:

    - the client must analyse every response and, if necessary, ask for
    more input from the user. IMO it would be best to design it so it
    can accept several commands, with 'quit' being one of them. Either
    that or all request/response pairs must be designed so that the client
    can always send a single request, output the result and exit no matter
    what the server returns.

    - the server must always return a response to every possible request
    or log a failure reason, preferably to the system log which is
    /var/log/messages in Linux, and die. The server must thoroughly
    validate requests and return an adequate error message if errors were
    found. I'd strongly suggest that every request generates a single
    (newline terminated?) response message because that makes error
    detection much easier. If the response is multi-line, send it as a
    single line, possibly as a comma-separated list, and let the client
    format it for display

    I tend to precede every request and response message with a fixed length
    byte count: this way the recipient process always knows how many bytes to
    read and can report errors if the received length is wrong. Using an 'end
    of message marker' (NEWLINE unless a message can legally contain internal
    newlines) can also be useful. I tend to put an error flag in the response
    message because this simplifies the client. I also design all messages to
    be plain ASCII because this makes debugging a lot easier. If things
    really turn to worms you can use wireshark to watch the traffic and read
    it straight off the screen without needing to decode binary values, etc.
    So, an invalid request and response might look like this:

    Request: "0013,WHOIS,elvis\n"
    Response: "0030,ERROR,Unknown request: WHOIS\n"

    > The inetd configuration is:
    > myservice stream tcp nowait root /local/daemon.py daemon.py
    >

    From what I recall about inetd that should be OK - I guess it must be
    since you can get one request through, and I assume (you didn't say) that
    a second request is also accepted without restarting the server.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
     
    Martin Gregorie, Feb 17, 2011
    #5
  6. Tim

    Tim Guest

    Re: client server socket interaction (inetd)

    On Feb 17, 6:09 pm, Martin Gregorie <>
    wrote:
    > On Thu, 17 Feb 2011 13:02:08 -0800, Tim wrote:
    > > But. The server may encounter a problem
    > > during the process and ask the user for more information like
    > > 'abort/retry' or something like that.

    >
    > Servers never ask the client for information: they are strictly request/
    > response handlers. To do what you're asking about, you'll need to change
    > both the client and server:
    >
    > - the client must analyse every response and, if necessary, ask for
    >   more input from the user. IMO it would be best to design it so it
    >   can accept several commands, with 'quit' being one of them. Either
    >   that or all request/response pairs must be designed so that the client
    >   can always send a single request, output the result and exit no matter
    >   what the server returns.
    >
    > - the server must always return a response to every possible request
    >   or log a failure reason, preferably to the system log which is
    >   /var/log/messages in Linux, and die. The server must thoroughly
    >   validate requests and return an adequate error message if errors were
    >   found. I'd strongly suggest that every request generates a single
    >   (newline terminated?) response message because that makes error
    >   detection much easier. If the response is multi-line, send it as a
    >   single line, possibly as a comma-separated list, and let the client
    >   format it for display
    >
    > I tend to precede every request and response message with a fixed length
    > byte count: this way the recipient process always knows how many bytes to
    > read and can report errors if the received length is wrong. Using an 'end
    > of message marker' (NEWLINE unless a message can legally contain internal
    > newlines) can also be useful. I tend to put an error flag in the response
    > message because this simplifies the client. I also design all messages to
    > be plain ASCII because this makes debugging a lot easier. If things
    > really turn to worms you can use wireshark to watch the traffic and read
    > it straight off the screen without needing to decode binary values, etc.
    > So, an invalid request and response might look like this:
    >
    > Request:   "0013,WHOIS,elvis\n"
    > Response:  "0030,ERROR,Unknown request: WHOIS\n"
    >
    > > The inetd configuration is:
    > > myservice  stream tcp nowait root /local/daemon.py daemon.py

    >
    > From what I recall about inetd that should be OK - I guess it must be
    > since you can get one request through, and I assume (you didn't say) that
    > a second request is also accepted without restarting the server.
    >
    > --
    > martin@   | Martin Gregorie
    > gregorie. | Essex, UK
    > org       |


    Thanks for helping me to understand. I don't know if you're familiar
    with LaTeX, but that's part of what daemon.py calls via subprocess,
    and that is the underlying process I wanted the user to be able to
    interact with.

    When LaTeX encounters a problem it stops processing, asks the user
    what to do (like abort/retry, kind-of), and does whatever the user
    says. The daemon.py script handles that okay from the command line,
    but if I'm understanding you this will be much harder if not
    impossible to accomplish from a client communicating over a socket.

    I thought that maybe I needed to fork the socket (somehow) so it could
    listen after the message is sent, but it looks like it will be more
    complex.

    thanks, I'm going to back to reading more on socket programming.
    --Tim
     
    Tim, Feb 18, 2011
    #6
  7. Re: client server socket interaction (inetd)

    On Fri, 18 Feb 2011 07:23:35 -0800, Tim wrote:

    > Thanks for helping me to understand. I don't know if you're familiar
    > with LaTeX, but that's part of what daemon.py calls via subprocess, and
    > that is the underlying process I wanted the user to be able to interact
    > with.
    >

    I've used nroff but never LaTeX - however, my understanding is that its
    essentially a batch process.

    > When LaTeX encounters a problem it stops processing, asks the user what
    > to do (like abort/retry, kind-of), and does whatever the user says. The
    > daemon.py script handles that okay from the command line, but if I'm
    > understanding you this will be much harder if not impossible to
    > accomplish from a client communicating over a socket.
    >

    Are you sure it wouldn't be better to end the run, returning suitable
    error messages to the user, who would correct the input file(s) and rerun
    LaTex?

    > I thought that maybe I needed to fork the socket (somehow) so it could
    > listen after the message is sent, but it looks like it will be more
    > complex.
    >

    The easier way my be to give the user a login to a captive shell that's
    restricted to running LateX, an editor and little else apart from a
    results viewer. Bash and most decent editors can be restricted so the
    user can't start a second, less restricted shell, and the range of
    programs it can execute can be restricted by adjusting with $PATH.

    You may also be able to find a menu program that can impose many of those
    restrictions by replacing the login's shell by the menu program. I do
    this as a matter of course: my menu program may get released one of these
    days but it's not currently on a fit state to publish.

    If you want to continue down the server path you should investigate popen.
    It is part of the os module. You could design the server so a suitable
    request runs LaTeX via popen, captures the stdout and stderr output, if
    any, and returns that and the LaTeX termination status code to the client
    as a response message.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
     
    Martin Gregorie, Feb 18, 2011
    #7
  8. Tim

    Nobody Guest

    Re: client server socket interaction (inetd)

    On Fri, 18 Feb 2011 07:23:35 -0800, Tim wrote:

    > When LaTeX encounters a problem it stops processing, asks the user
    > what to do (like abort/retry, kind-of), and does whatever the user
    > says. The daemon.py script handles that okay from the command line,
    > but if I'm understanding you this will be much harder if not
    > impossible to accomplish from a client communicating over a socket.


    The difficulty of achieving this is unrelated to the use of a socket. It's
    an issue of whether you have a user available to respond to any prompts,
    or whether the client has to be able to do this itself.

    If you want to "script" an interactive program, you need to be able to
    recognise prompts and respond appropriately. If the program was designed
    to interact with a human, this can be far from straightforward. But the
    method of communication (pipes versus sockets) isn't relevant.
     
    Nobody, Feb 18, 2011
    #8
    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. Sakagami Hiroki

    inetd like server socket supervisor in Java

    Sakagami Hiroki, Jun 7, 2006, in forum: Java
    Replies:
    2
    Views:
    2,115
    Martin Gregorie
    Jun 7, 2006
  2. Jan

    inetd script in python?

    Jan, Feb 27, 2004, in forum: Python
    Replies:
    4
    Views:
    2,525
    Donn Cave
    Mar 1, 2004
  3. Marek Kubica

    SimpleXMLServer meets inetd

    Marek Kubica, Mar 12, 2005, in forum: Python
    Replies:
    0
    Views:
    327
    Marek Kubica
    Mar 12, 2005
  4. Obi-Wan

    Stdout to UDP socket in inetd

    Obi-Wan, Mar 10, 2006, in forum: C Programming
    Replies:
    3
    Views:
    455
    Keith Thompson
    Mar 11, 2006
  5. Mark_Galeck
    Replies:
    3
    Views:
    260
    Mark_Galeck
    Aug 16, 2009
Loading...

Share This Page