By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,294 Members | 2,681 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,294 IT Pros & Developers. It's quick & easy.

Client/Server socket send user input

P: n/a
jas
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.sock)
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.

Oct 25 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
jas
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
[/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:\>
[cursor_is_here]

[/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.

Oct 25 '05 #2

P: n/a
On 25 Oct 2005 12:39:06 -0700, "jas" <co*******@gmail.com> declaimed the
following in comp.lang.python:

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


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.Popen(command,
stdout=subprocess.PIPE,
stdin=subprocess.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.Thread(target=self.readChar)
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.Thread(target=self.readLine)
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.stdout.read(1)

# get the lock to access the character list, append it
self.charLock.acquire()
self.charList.append(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.release()

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.timeOut)
# get the lock allowing access to the character list
self.charLock.acquire()
# 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.release()
# 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(lineChar))
lineChar = []
else:
# time out, assume prompt stage, queue partial line
self.lineQueue.put("".join(lineChar))
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.stdin.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("\nApplication Prompt (<ctrl-z> to exit)>
")
myCommand.send(UserData + "\n")
except:
break

myCommand.send("exit\n")

myCommand.shutdown()

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

E:\UserData\Dennis Lee Bieber\My Documents>python script2.py

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

E:\UserData\Dennis 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\Dennis 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.pdf
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.xml
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.I20050627-1435.pdf
06/27/2005 03:19 PM 6,791,109
org.eclipse.platform.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.jpg
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.ads
06/24/2005 08:49 PM 1,144 student_pack.ads.0
06/24/2005 08:56 PM 1,342 student_pack.ali
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\Dennis 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\Dennis Lee Bieber\My Documents>
***** End capture

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

E:\UserData\Dennis Lee Bieber\My Documents>
-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Oct 26 '05 #3

P: n/a
jas
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.

Oct 26 '05 #4

P: n/a
On 26 Oct 2005 04:49:20 -0700, "jas" <co*******@gmail.com> declaimed the
following in comp.lang.python:
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.
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.

-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Oct 26 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.