/ / Python: Synchronisieren von Eingabe und Ausgabe zwischen Threads - Python, Eingabe, Multithreading

Python: Synchronisieren von Eingabe und Ausgabe zwischen Threads - Python, Eingabe, Multithreading

Momentan versuche ich ein kleines Projekt mit Sockets in Python, einem Zwei-Benutzer-Chat-System, zu machen.

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()

(Ich hoffe die Kommentare helfen)

Wie auch immer, indem gleichzeitig nach Eingabe gefragt wird,und bekomme die Nachricht des anderen Sockets, ich habe ein kleines Synchronisationsproblem. Ich kann eine Verbindung herstellen, aber wenn ich eine Nachricht erhalte, wird die Eingabeanweisung nicht abgebrochen.

Mit anderen Worten, wenn ich eine Nachricht erhalte, sagt sie das

Message: user: I got a message
#Flashing cursor here

Damit wird die Eingabeanweisung nicht abgebrochen.

Außerdem bekomme ich nur jede andere Nachricht.

Irgendwelche Vorschläge?

Antworten:

1 für die Antwort № 1

Was Sie hier haben, ist nicht so sehr einSynchronisierungsproblem, da es sich um ein Problem mit der Präsentation / Benutzeroberfläche handelt. Ich würde vorschlagen, Ihr Leben einfacher zu machen und einige UI-Toolkits (Flüche, wxPython, pyqt) auszuwählen, um die Interaktion mit dem Benutzer zu handhaben. Die Verwendung von input () ist sehr praktisch für schnellen und einfachen Code, aber es ist nicht sehr anspruchsvoll.

Wenn Sie dies tun, werden Sie sehen, dass Sie gar keine Threads verwenden müssen (wie es oft der Fall ist), und Ihre Probleme verschwinden wie durch Zauberei!


1 für die Antwort № 2

In Ordnung, Entschuldigung für eine so schnelle Antwort auf meine eigene Frage, aber Callbacks sind MAGICAL bei der Verwendung von Threading (zumindest auf Linux-Modell).

Wie auch immer, tat dies:

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...nn" + 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()

Wie Sie sehen können, habe ich die Nachrichtenschleife als Rückruf hinzugefügt.

Beachten Sie auch, ich sende einen Nullwert, um das "jedes andere" Problem zu umgehen.

Das und ich benutze einen Zeilenumbruch am Ende des Druckvorgangs in data_recieved, um den Zeilenumbruch zu deaktivieren.

(Wenn Sie den Code mögen, läuft er unter Windows nicht so gut. Das liegt daran, dass Pythons Threading-Modell anscheinend nicht so konsequent ausgeführt wird. Versuchen Sie es in Ihrer lokalen Linux-Box.)