Python Zugang zu BaseRequestHandler
-
21-09-2019 - |
Frage
Mein Code muss im Grunde einen einfachen Chat-Server mit einem Client starten. Wo der Server und der Client können hin und her miteinander reden. Ich habe alles bekommen richtig umgesetzt werden, aber ich kann nicht herausfinden, wie man den Server herunterzufahren, wenn ich fertig bin. (Ich weiß, es ist ss.shutdown()
).
Ich will jetzt beenden, basierend auf einem Schlüsselwort zwischen den beiden (so etwas wie "bye"
) geteilt, aber ich weiß nicht, ob ich irgendwie eine Nachricht an meine SocketServer
von BaseRequestHandler
zu shutdown()
senden kann, wenn er die Nachricht erhält .
Schließlich ist es mein Ziel ist Tkinter
zu integrieren, um eine GUI zu machen, aber ich wollte alles anderes zur Arbeit kommen zuerst, und dies ist mein erstes Mal mit Steckdosen in Python zu tun.
from sys import argv, stderr
from threading import Thread
import socket
import SocketServer
import threading
import sys
class ThreadedRecv(Thread):
def __init__(self,socket):
Thread.__init__(self)
self.__socket = socket
self.__message = ''
self.__done = False
def recv(self):
while self.__message.strip() != "bye" and not self.getStatus():
self.__message = self.__socket.recv(4096)
print 'received',self.__message
self.setStatus(True)
def run(self):
self.recv()
def setStatus(self,status):
self.__done = status
def getStatus(self):
return self.__done
class ThreadedSend(Thread):
def __init__(self,socket):
Thread.__init__(self)
self.__socket = socket
self.__message = ''
self.__done = False
def send(self):
while self.__message != "bye" and not self.getStatus():
self.__message = raw_input()
self.__socket.send(self.__message)
self.setStatus(True)
def run(self):
self.send()
def setStatus(self,status):
self.__done = status
def getStatus(self):
return self.__done
class HostException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class EchoServer(SocketServer.BaseRequestHandler):
def setup(self):
print self.client_address, 'is connected!'
self.request.send('Hello ' + str(self.client_address) + '\n')
self.__done = False
def handle(self):
sender = ThreadedSend(self.request)
recver = ThreadedRecv(self.request)
sender.start()
recver.start()
while 1:
if recver.getStatus():
sender.setStatus(True)
break
if sender.getStatus():
recver.setStatus(True)
break
def finish(self):
print self.client_address, 'disconnected'
self.request.send('bye client %s\n' % str(self.client_address))
self.setDone(True)
def setDone(self,done):
self.__done = done
def getDone(self):
return self.__done
def setup(arg1, arg2, arg3):
server = False
defaultPort,defaultHost = 2358,"localhost"
hosts = []
port = defaultPort
serverNames = ["TRUE","SERVER","S","YES"]
arg1 = arg1.upper()
arg2 = arg2.upper()
arg3 = arg3.upper()
if arg1 in serverNames or arg2 in serverNames or arg3 in serverNames:
server = True
try:
port = int(arg1)
if arg2 != '':
hosts.append(arg2)
except ValueError:
if arg1 != '':
hosts.append(arg1)
try:
port = int(arg2)
if arg3 != '':
hosts.append(arg3)
except ValueError:
if arg2 != '':
hosts.append(arg2)
try:
port = int(arg3)
except ValueError:
if arg3 != '':
hosts.append(arg3)
port = defaultPort
for sn in serverNames:
if sn in hosts:
hosts.remove(sn)
try:
if len(hosts) != 1:
raise HostException("Either more than one or no host "+ \
"declared. Setting host to localhost.")
except HostException as error:
print error.value, "Setting hosts to default"
return (server,defaultHost,port)
return (server,hosts[0].lower(),port)
def main():
bufsize = 4096
while len(argv[1:4]) < 3:
argv.append('')
settings = setup(*argv[1:4])
connections = (settings[1],settings[2])
print connections
if not settings[0]:
try:
mySocket = socket.socket(socket.AF_INET,\
socket.SOCK_STREAM)
except socket.error, msg:
stderr.write("[ERROR] %s\n" % msg[1])
sys.exit(1)
try:
mySocket.connect(connections)
except socket.error, msg:
stderr.write("[ERROR] %s\n" % msg[1])
sys.exit(2)
message = ""
print "Enter a message to send to the server. "+\
"Enter \"bye\" to quit."
sender = ThreadedSend(mySocket)
recver = ThreadedRecv(mySocket)
sender.start()
recver.start()
while 1:
if sender.getStatus():
recver.setStatus(True)
break
if recver.getStatus():
sender.setStatus(True)
break
else:
xserverhandler = EchoServer
serversocket = SocketServer.ThreadedTCPServer(\
connections,xserverhandler)
server_thread = Thread(target = serversocket.serve_forever)
server_thread.setDaemon(True)
server_thread.start()
# I would like to shut down this server whenever
# I get done talking to it.
"""while 1:
if xserverhandler.getDone():
print 'This is now true!'
serversocket.shutdown()
break"""
if __name__ == '__main__':
main()
Ja, ich weiß setup () ist eine schreckliche Funktion jetzt mit dem Versuch der Fangmengen, aber es funktioniert jetzt, so dass ich es würde später beheben.
Meine Frage ist im Grunde: Wie kann ich den Server erhalten, um tatsächlich auf einem Nachrichtenende aus, dass es erhält? Wenn möglich, ist es eine Möglichkeit, die Request-Handler zugreifen, nachdem er gestartet wird?
Lösung
Bitte korrigieren Sie Ihren Code, damit es funktioniert, und sind in gewisser Weise, es zu benutzen. Sie müssen hinzufügen
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
da Socket eigentlich nicht diese Klasse gehört (zumindest nicht in meiner Version 2.6 noch 2.7). Stattdessen ist es ein Beispiel aus der Socket Definition .
Bitte geben Sie ein Beispiel, wie Sie den Code starten / verwenden. In diesem Fall den Server starten Sie tun müssen:
ss.py SERVER localhost 8001
und der Client als
ss.py localhost 8001
Wenn Sie das tun, dann können Sie nicht server_thread.setDaemon (True) tun, weil es keine anderen Threads ausgeführt wird, was bedeutet, dass der Server sofort verlassen wird.
Sobald, dass die Lösung getan ist, einen Anruf (oder zwei) zu self.server.shutdown () insdie Ihre EchoServer.handle Methode hinzufügen, wie:
while 1:
if recver.getStatus():
sender.setStatus(True)
self.server.shutdown()
break
Allerdings kann ich nicht, dass an der Arbeit, und ich denke, es ist, weil ich Dinge falsch geerbt, oder erraten falsch in dem, was Sie getan haben.
Was Sie tun sollten, ist Suche nach jemanden, der einen Chat-Server in Python getan hat. Mit Google fand ich http://www.slideshare.net/didip/socket- Programmierung-in-python und es gibt sicherlich andere.
Auch wenn Sie vorhaben, GUI zu mischen und Gewinde Programmierung dann sollten Sie Beispiele sehen in basierend darauf. Es gibt eine Reihe von Hits, als ich für „tkinter Chat“ gesucht. Auch Sie könnten in verdreht aussehen wollen, die viele dieser Probleme bereits gelöst hat.
Was Probleme? Nun, zum Beispiel, wollen Sie wahrscheinlich eine SO_REUSEADDR Socket-Option.
Andere Tipps
Request-Handler-Objekt wird für jede neue Anforderung erstellt. So Sie speichern müssen „Fertig“ -Flag in Server, nicht Handler. Etwas wie folgt aus:
class EchoServer(SocketServer.BaseRequestHandler):
...
def setDone(self):
self.server.setDone() # or even better directly self.server.shutdown()