Python:同步线程之间的输入和输出
目前,我正在尝试使用Python中的套接字(一种双用户聊天系统)做一个小型项目。Python:同步线程之间的输入和输出
import socket
import threading
#Callback. Print doesn't work across threads
def data_recieved(data):
print data
#Thread class to gather input
class socket_read(threading.Thread):
sock = object
def __init__(self, sock):
threading.Thread.__init__(self)
self.sock = sock
def run(self):
while True:
data = self.sock.recv(1000)
if (data == "\quitting\\"):
return
data_recieved(self.sock.recv(1000))
####################################################################################
server = False
uname = input("What's your username: ")
print "Now for the technical info..."
port = input("What port do I connect to ['any' if first]: ")
#This is the first client. Let it get an available port
if (port == "any"):
server = True
port = 9999
err = True
while err == True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', port))
err = False
except:
err = True
sock.close()
print "Bound to port #" + str(port)
print "Waiting for client..."
sock.listen(1)
(channel, info) = sock.accept()
else:
#This is the client. Just bind it tho a predisposed port
host = input("What's the IP of the other client: ")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, int(port)))
msg = ""
if (server == True):
#Use the connection from accept
reader = socket_read(channel)
else:
#Use the actual socket
reader = socket_read(sock)
reader.start()
while msg != 'quit':
#Get the message...
msg = uname + ": " + input("Message: ")
try:
#And send it
if (server == True):
#Use the connection from accept
channel.send(msg)
else:
#Use direct socket
sock.send(msg)
except:
break
reader.join()
channel.send("\quitting\\")
sock.close()
(我希望评论帮助)
总之,通过调用输入的同时,并获得对方套接字的消息时,我有一个小的同步化问题。我可以连接,但是当我收到消息时,它不会取消输入语句。
换句话说,当我收到一个消息,它说这个
Message: user: I got a message
#Flashing cursor here
因此,它不会取消输入语句。
此外,我只收到其他所有消息。
有什么建议吗?
你在这里所做的并不是一个同步问题,因为它是一个演示/ UI问题。我建议让你的生活更轻松,并选择一些UI工具包(curses,wxPython,pyqt)来处理与用户的交互。使用input()对于快速而肮脏的一次性代码非常方便,但它并不十分复杂。
如果你这样做,你会看到你根本不需要使用线程(就像往常一样),你的问题就会像魔术一样消失!
好吧,对于我自己的问题,很抱歉这么快速回答,但使用线程时(至少在Linux的模型上),回调是神奇的。
总之,这样做:
import socket
import threading
def msg_loop(socket):
msg = ""
if (server == True):
reader = socket_read(channel)
else:
reader = socket_read(sock)
reader.start()
while msg != 'quit':
msg = uname + " said : " + input("Message: ")
print ""
try:
if (server == True):
channel.send('null')
channel.send(msg)
else:
sock.send('null')
sock.send(msg)
except:
break
def data_recieved(data, socket):
print "Hold on...\n\n" + data + "\n"
msg_loop(socket)
class socket_read(threading.Thread):
sock = object
def __init__(self, sock):
threading.Thread.__init__(self)
self.sock = sock
def run(self):
while True:
data = self.sock.recv(1000)
if (data == "\quitting\\" or data == ''):
return
data_recieved(self.sock.recv(1000), self.sock)
####################################################################################
server = False
uname = str(input("What's your username: "))
print "Now for the technical stuff..."
port = input("What port do I connect to ['any' if first]: ")
if (port == "any"):
server = True
port = 9999
err = True
while err == True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', port))
err = False
except:
print "Socket #" + str(port) + " failed"
err = True
sock.close()
port -= 1
print "Bound to port #" + str(port)
print "Waiting for client..."
sock.listen(1)
(channel, info) = sock.accept()
else:
host = input("What's the IP of the other client: ")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, int(port)))
if (server == True):
msg_loop(channel)
else:
msg_loop(sock)
reader.join()
channel.send("\quitting\\")
sock.close()
正如你所看到的,我加了消息循环作为回调。
另请注意,我发送空值,以规避“其他”问题。
那,我在data_recieved的打印结束处使用换行符来禁用换行符。
(如果你喜欢的代码,它不运行,以及在Windows上,这是因为,很显然,在那里Python的线程模型不作为instentaniously执行。尝试在您的本地Linux框)
这看起来不正确。 如果你一直在调用data_recieved和socket_read而不返回,你最终会崩溃。 – drxzcl 2009-12-21 15:41:36
次要注意事项:“received”拼写错误,您使用的“回调”不仅不是回调(它只是一个常规的函数调用),而是没用的......用打印替换该调用,您将得到相同的结果。最后,input()是危险的,因为它在用户输入上调用eval():相反,使用raw_input()会更安全,这可以做你可能认为input()所做的事情。 – 2009-12-21 15:10:40
感谢您的想法。我刚碰到一个逗号错误,这个错误是固定的。 – new123456 2009-12-21 15:34:27