Client/Server socket send user input

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • jas

    #1

    Client/Server socket send user input

    I have a basic client/server socket situation setup....where the server
    accepts a connection and then waits for commands.

    On the client side, I create a socket, connect to the server...then I
    pass the socket to a class which just reads from the socket (in a
    thread).

    class Reader(Thread):
    def run(self):
    while 1:
    print self.sock.recv( 1),

    Now, when the server sends back a message, and needs input back the
    reader hangs at the sock.recv line...which is fine, and expected.
    However, I want to be able to type something into the console at that
    point and hit enter, and have it sent to the server.

    In my client class I tried something like...

    class Client(Thread):
    def run(self):
    reader = Reader(self.soc k)
    reader.start()
    while 1:
    x = raw_input("go>" )
    self.sock.send( x)
    print "sent", x

    However, in order to see "go>" ..I have to hit enter first, then type
    in my command and hit enter to send. I just want to type and hit
    enter.

    Any ideas/suggestions?

    Thanks.

  • jas

    #2
    Re: Client/Server socket send user input

    I even tried inserting a "\r" or "\r\n" or "\n" to stdout, also tried
    the same using msvcrt.putch() ...but no luck. I still have to hit
    enter to get the prompt , where I can then type a command and hit
    enter.

    For example, I get this displayed:
    [example]
    Microsoft Windows XP [Version 5.1.2600]
    (C) Copyright 1985-2001 Microsoft Corp.

    C:\>[cursor_is_here]
    [/example]

    ....so I type something like.."ver" but I get

    [example]
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    NameError: name 'ver' is not defined[color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]
    [/example]

    Now, if I start over and have...

    [example]
    Microsoft Windows XP [Version 5.1.2600]
    (C) Copyright 1985-2001 Microsoft Corp.

    C:\>[cursor_is_here]
    [/example]

    ...and I press the Enter key I end up with

    [example]
    Microsoft Windows XP [Version 5.1.2600]
    (C) Copyright 1985-2001 Microsoft Corp.

    C:\>
    [color=blue][color=green][color=darkred]
    >>>[cursor_is_here][/color][/color][/color]
    [/example]

    So, I get the prompt, I hit enter, which then displays the ">>>" ..and
    if I type "ver" there, I get back what I expect.

    I just wish I didn't have to hit enter before being able to type a
    command.

    Comment

    • Dennis Lee Bieber

      #3
      Re: Client/Server socket send user input

      On 25 Oct 2005 12:39:06 -0700, "jas" <codecraig@gmai l.com> declaimed the
      following in comp.lang.pytho n:

      [color=blue]
      > Traceback (most recent call last):
      > File "<stdin>", line 1, in ?
      > NameError: name 'ver' is not defined[color=green][color=darkred]
      > >>>[/color][/color]
      > [/example][/color]

      That >>> tells us that you are running inside the interactive PYTHON
      interpreter. That means you now have TWO processes trying to read from
      the SAME keyboard/console window, and they are likely going to be taking
      turns... Python is going to put out its prompt while the subprocess is
      starting, and queues ITS read statement -- the subprocess then puts out
      ITS prompt and queues a read. You type something, and the FIRST read
      sees it -- the Python interactive interpreter.

      Here's the latest mod on my massive test sample... No changes to the
      "shell" class -- it was already rigged to pipe data in both directions
      (the subprocess is NOT trying to read the keyboard/console). Instead of
      passing in canned test commands I now made a loop that does a "capture"
      until "None" is returned (time-out), then the PYTHON program prompts for
      a command to be sent on to the subprocess.

      -=-=-=-=-=-=-=-=-
      import subprocess
      import os
      import threading
      import Queue


      class Shell(object):
      def __init__(self, command):
      # flag for shutdown
      self.die = False

      self.timeOut = 1.0

      # queue for buffering "lines"
      self.lineQueue = Queue.Queue()

      # list for collecting characters read from subprocess
      # allows for character reader to collect characters
      # while line reader processes a prior batch
      self.charList = []

      # event to signal that, at least, one character is
      # available. event is used to allow time-out wait()
      self.charEvent = threading.Event ()

      # event to signal that something has been written to the
      # subprocess, and that the line reader should start
      # collecting stuff (this is used to avoid multiple "prompt"
      # timeouts from falsely affecting the user
      self.lineEvent = threading.Event ()

      # lock to wrap access to self.charList
      self.charLock = threading.Lock( )

      # create subprocess object with supplied command
      self.process = subprocess.Pope n(command,
      stdout=subproce ss.PIPE,
      stdin=subproces s.PIPE)

      # initialize, and start the character reader
      # thread -- this is the thread that actually reads the
      # subprocess output stream, one character at a time
      self.charThread = threading.Threa d(target=self.r eadChar)
      self.charThread .start()

      # initialize, and start the line reader thread
      # -- this is the thread that processes collected characters
      # OR on a timeout of the event, queues up a prompt and
      # then busy-waits until the queue is empty (meaning the
      # user application has processed up to
      self.lineThread = threading.Threa d(target=self.r eadLine)
      self.lineThread .start()

      # set the line event so the line reader knows it should read
      up
      # to the next time-out/prompt
      self.lineEvent. set()

      def readChar(self):
      while not self.die:
      # read one character at a time from subprocess; blocks
      ch = self.process.st dout.read(1)

      # get the lock to access the character list, append it
      self.charLock.a cquire()
      self.charList.a ppend(ch)
      # signal the line reader that, at least one, character
      # is in the list
      self.charEvent. set()
      # let the line reader access the character list
      self.charLock.r elease()

      def readLine(self):
      lineChar = []
      while not self.die:
      # block until told that the subprocess has been commanded
      # and thereby should be producing some sort of output
      self.lineEvent. wait()
      # block for up to one second waiting for the character
      # reader to produce some sort of output
      self.charEvent. wait(self.timeO ut)
      # get the lock allowing access to the character list
      self.charLock.a cquire()
      # clear the character reader event so the next pass
      # will block(time-out) if no more data
      self.charEvent. clear()
      # save the character list locally so the character reader
      # can add more stuff to it (after clearing it)
      tCharList = self.charList
      self.charList = []
      # release the character list lock so reader can touch it
      self.charLock.r elease()
      # if the list is not empty, we have some data
      if tCharList:
      # process each character looking for a new line
      character
      # note: no filtering is done, all characters will be
      # returned to user
      for ch in tCharList:
      lineChar.append (ch)
      # on a new line, collect all preceding and make a
      # string out of them, queue the string
      if ch == "\n":
      self.lineQueue. put("".join(lin eChar))
      lineChar = []
      else:
      # time out, assume prompt stage, queue partial line
      self.lineQueue. put("".join(lin eChar))
      lineChar = []
      # queue None as signal
      self.lineQueue. put(None)
      # AND clear the line event so we don't try to read
      # anymore data (and get time-out/prompts) until the
      # user has sent some command
      self.lineEvent. clear()

      def input(self):
      # return the next available data line (which may be None for
      # time-out/prompt. This will BLOCK if called when the queue
      # is empty
      return self.lineQueue. get()

      def empty(self):
      # return the state of the line queue
      return self.lineQueue. empty()

      def send(self, data, timeout = 1.0):
      # send the data to the subprocess
      self.process.st din.write(data)
      # reset the timeout value -- this allows the user to specify
      # a long timeout for known number crunchers so that one
      # doesn't get an errorneous (early) "prompt" indication
      self.timeOut = timeout
      # signal the line reader that data has been sent, and it
      # should start processing return data
      self.lineEvent. set()

      def shutdown(self):
      self.die = True
      self.charEvent. set()
      self.charThread .join()
      self.lineEvent. set()
      self.lineThread .join()


      myCommand = Shell("cmd.exe" )

      while True:
      try:
      print "\n***** Start capture"
      while True:
      ln = myCommand.input ()
      if not ln: break
      print ln,
      print "\n***** End capture"
      UserData = raw_input("\nAp plication Prompt (<ctrl-z> to exit)>
      ")
      myCommand.send( UserData + "\n")
      except:
      break

      myCommand.send( "exit\n")

      myCommand.shutd own()

      -=-=-=-=-=-=-

      E:\UserData\Den nis Lee Bieber\My Documents>pytho n script2.py

      ***** Start capture
      Microsoft Windows XP [Version 5.1.2600]
      (C) Copyright 1985-2001 Microsoft Corp.

      E:\UserData\Den nis Lee Bieber\My Documents>
      ***** End capture

      Application Prompt (<ctrl-z> to exit)> dir

      ***** Start capture
      dir
      Volume in drive E is Data
      Volume Serial Number is 2626-D991

      Directory of E:\UserData\Den nis Lee Bieber\My Documents

      10/25/2005 09:03 PM <DIR> .
      10/25/2005 09:03 PM <DIR> ..
      07/25/2005 10:39 PM <DIR> .metadata
      10/06/2005 09:54 AM <DIR> Ada Progs
      08/13/2005 02:01 PM <DIR> Agent Data
      10/21/2005 09:29 AM 421,820 apress_offer.pd f
      07/03/2005 11:36 AM 132 cp.py
      07/17/2005 12:25 PM <DIR> Cyberlink
      07/06/2005 09:32 AM 102,400 db1.mdb
      07/26/2005 12:20 AM 26,614 eclipse_code.xm l
      10/25/2005 08:06 PM <DIR> Eudora
      06/24/2005 08:50 PM 667 fake_oosums.ads
      06/24/2005 08:50 PM 695 fake_oosums.ali
      09/06/2005 09:01 PM <DIR> Genealogy
      07/13/2005 10:56 PM <DIR> HomeSite
      05/08/2005 01:05 PM <DIR> Investing
      10/21/2005 10:04 PM <DIR> Java Progs
      08/04/2005 10:13 PM 162 main.py
      10/11/2005 10:43 PM <DIR> My Downloads
      05/01/2005 10:31 AM <DIR> My eBooks
      04/22/2005 12:09 AM <DIR> My Music
      07/10/2005 11:43 AM <DIR> My Pictures
      06/29/2005 11:55 PM <DIR> My PSP Files
      05/23/2005 09:30 AM <DIR> My Videos
      05/01/2005 12:49 PM <DIR> Office Documents
      06/27/2005 03:19 PM 7,961,778
      org.eclipse.jdt .doc.user.I2005 0627-1435.pdf
      06/27/2005 03:19 PM 6,791,109
      org.eclipse.pla tform.doc.user. I20050627-1435.pdf
      10/11/2005 10:52 PM 56 oth_tsr_rm_750. ram
      07/20/2005 09:32 AM 108,457 parkerred15yc.j pg
      09/03/2005 10:36 PM <DIR> Python Progs
      10/25/2005 08:16 PM <DIR> Quicken
      07/10/2005 12:09 PM 3,356,248 results.xml
      06/11/2005 12:03 PM 935 Scout_Ship Database.lnk
      07/03/2005 12:38 PM <DIR> Scout_Ship My Documents
      10/24/2005 09:23 AM 971 Script1.py
      09/25/2005 12:40 PM 1,107 Script1_old.py
      10/25/2005 09:03 PM 6,352 Script2.py
      08/28/2005 11:47 AM <DIR> SimpleMu Logs
      06/24/2005 08:56 PM 1,201 student_pack.ad s
      06/24/2005 08:49 PM 1,144 student_pack.ad s.0
      06/24/2005 08:56 PM 1,342 student_pack.al i
      08/02/2005 11:39 PM 4,096 t.DOC
      06/20/2005 10:11 AM 104 t.rx
      08/05/2005 08:41 PM 66,452 Untitled-1.tif
      08/05/2005 08:41 PM <DIR> VCheck
      10/03/2005 02:58 AM <DIR> Visual Studio
      10/03/2005 02:51 AM <DIR> Visual Studio 2005
      22 File(s) 18,853,842 bytes
      25 Dir(s) 267,148,263,424 bytes free

      E:\UserData\Den nis Lee Bieber\My Documents>
      ***** End capture

      Application Prompt (<ctrl-z> to exit)> time

      ***** Start capture
      time
      The current time is: 21:04:25.74
      Enter the new time:
      ***** End capture

      Application Prompt (<ctrl-z> to exit)>

      ***** Start capture


      E:\UserData\Den nis Lee Bieber\My Documents>
      ***** End capture

      Application Prompt (<ctrl-z> to exit)> ^Z

      E:\UserData\Den nis Lee Bieber\My Documents>
      --[color=blue]
      > =============== =============== =============== =============== == <
      > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
      > wulfraed@dm.net | Bestiaria Support Staff <
      > =============== =============== =============== =============== == <
      > Home Page: <http://www.dm.net/~wulfraed/> <
      > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]

      Comment

      • jas

        #4
        Re: Client/Server socket send user input

        Dennis,
        Thanks. That certainly looks like it could work. I understand
        about the interactive shell and my app going back and forth with the
        reads/writes. When my program runs it won't be used in an interactive
        python shell, but that is the only way I know of to really test it.

        Comment

        • Dennis Lee Bieber

          #5
          Re: Client/Server socket send user input

          On 26 Oct 2005 04:49:20 -0700, "jas" <codecraig@gmai l.com> declaimed the
          following in comp.lang.pytho n:
          [color=blue]
          > Dennis,
          > Thanks. That certainly looks like it could work. I understand
          > about the interactive shell and my app going back and forth with the
          > reads/writes. When my program runs it won't be used in an interactive
          > python shell, but that is the only way I know of to really test it.[/color]

          Do what I do... Open a command shell, and run from there using a
          simple "python whatever.py"; just use IDLE or PythonWin for editing,
          saving the file before each test.

          --[color=blue]
          > =============== =============== =============== =============== == <
          > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
          > wulfraed@dm.net | Bestiaria Support Staff <
          > =============== =============== =============== =============== == <
          > Home Page: <http://www.dm.net/~wulfraed/> <
          > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]

          Comment

          Working...