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?

War es hilfreich?

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()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top