Question

Mon code a besoin essentiellement pour démarrer un simple serveur de chat avec un client. Lorsque le serveur et le client peut parler et-vient à l'autre. J'ai tout appris à être mis en œuvre correctement, mais je ne peux pas comprendre comment arrêter le serveur chaque fois que je suis fait. (Je sais que ss.shutdown() est ça).

Je suis désireux de mettre fin à ce moment basé sur un mot-clé partagé entre les deux (quelque chose comme "bye"), mais je ne sais pas si je peux en quelque sorte envoyer un message à mon SocketServer de BaseRequestHandler à shutdown() chaque fois qu'il reçoit le message .

Finalement, mon objectif est d'intégrer Tkinter de faire une interface graphique, mais je voulais faire tout le reste à travailler d'abord, ce qui est la première fois que traiter les sockets en Python.

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

Ouais, je sais que la configuration () est une fonction terribles en ce moment avec les captures de l'essai, mais il fonctionne pour l'instant, donc j'allais le corriger plus tard.

Ma question est fondamentalement: Comment puis-je obtenir le serveur pour mettre fin en fait basé sur un message qu'il reçoit? Si possible, est-il un moyen d'accéder à la demande Handler après qu'il a commencé?

Était-ce utile?

La solution

S'il vous plaît corriger votre code afin qu'il fonctionne, et inclure une certaine façon de l'utiliser. Vous devez ajouter

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

depuis SocketServer ne comprend pas vraiment cette classe (au moins pas dans ma version de 2.6 ni 2.7). Au lieu de cela, il est un exemple de la définition SocketServer .

S'il vous plaît inclure un exemple de la façon de démarrer / utiliser le code. vous devez faire dans ce cas pour démarrer le serveur:

ss.py SERVER localhost 8001

et le client comme

ss.py localhost 8001

Si vous faites cela, vous ne pouvez pas faire server_thread.setDaemon (vrai) parce qu'il n'y a pas d'autres threads en cours d'exécution, ce qui signifie que le serveur quitte immédiatement.

Une fois cela fait la solution consiste à ajouter un appel (ou deux) à self.server.shutdown () insdie de votre méthode EchoServer.handle, comme:

    while 1:
        if recver.getStatus():
            sender.setStatus(True)
            self.server.shutdown()
            break

Cependant, je ne peux pas que le travail, et je pense que c'est parce que je hérité de mauvaises choses, ou devinais mal dans ce que vous avez fait.

Ce que vous devez faire est de rechercher quelqu'un d'autre qui a fait un serveur de chat en Python. En utilisant Google J'ai trouvé http://www.slideshare.net/didip/socket- la programmation en python et il y a certainement d'autres.

En outre, si vous allez mélanger GUI et la programmation par thread alors vous devriez regarder dans des exemples sur cette base. Il y a un certain nombre de hits quand je recherchais « tkinter chat ». En outre, vous voudrez peut-être examiner tordu, qui a résolu beaucoup de ces problèmes déjà.

Quels sont les problèmes? Eh bien, par exemple, vous voulez probablement une option prise SO_REUSEADDR.

Autres conseils

Demande objet de gestion est créé pour chaque nouvelle demande. Donc, vous devez stocker « fait » drapeau serveur, et non gestionnaire. Quelque chose comme ce qui suit:

class EchoServer(SocketServer.BaseRequestHandler):
    ...
    def setDone(self):
        self.server.setDone() # or even better directly self.server.shutdown()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top