Domanda

Il mio codice ha bisogno fondamentalmente di avviare un semplice server di chat con un cliente. In cui il server e il client possono parlare avanti e indietro gli uni agli altri. Ho ottenuto tutto per essere attuato in modo corretto, ma non riesco a capire come spegnere il server ogni volta che ho finito. (Lo so che è ss.shutdown()).

Sono voler porre fine in questo momento sulla base di una parola chiave condivisa tra i due (qualcosa come "bye"), ma non so se posso in qualche modo inviare un messaggio al mio SocketServer da BaseRequestHandler a shutdown() ogni volta che riceve il messaggio .

Alla fine, il mio obiettivo è quello di incorporare Tkinter per fare una GUI, ma ho voluto ottenere tutto il resto al lavoro prima, e questa è la mia prima volta si tratta di prese in 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()

Sì, lo so setup () è una funzione terribile in questo momento con la prova e di catture, ma funziona per il momento, quindi stavo per risolvere il problema in seguito.

La mia domanda è fondamentalmente: Come posso ottenere il server per terminare in realtà basato su un messaggio che riceve? Se possibile, c'è un modo per accedere al gestore richieste dopo che è iniziato?

È stato utile?

Soluzione

Si prega di correggere il codice in modo che funziona, e includono un modo per usarlo. È necessario aggiungere

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

poiché SocketServer realtà non comprende quella classe (almeno non nella mia versione di 2.6 né 2.7). Invece, è un esempio dal SocketServer definizione .

Si prega di includere un esempio di come avviare / utilizzare il codice. In questo caso, per avviare il server che devi fare:

ss.py SERVER localhost 8001

e il cliente come

ss.py localhost 8001

Se lo fai, allora non si può fare server_thread.setDaemon (True) perché non ci sono altri thread in esecuzione, il che significa che il server uscire immediatamente.

Una volta fatto la soluzione è quella di aggiungere una chiamata (o due) per self.server.shutdown () insdie del metodo EchoServer.handle, come:

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

Tuttavia, non posso ottenere che per lavoro, e penso che sia perché ho ereditato cose sbagliate, o indovinato sbagliato in quello che hai fatto.

Che cosa si dovrebbe fare è cercare qualcun altro che ha fatto un server di chat in Python. Utilizzo di Google ho trovato http://www.slideshare.net/didip/socket- programmazione-in-python e ci sono certamente altri.

Inoltre, se avete intenzione di mescolare GUI e programmazione threaded allora si dovrebbe guardare in esempi basati su questo. Ci sono una serie di colpi quando ho cercato per "Tkinter chat". Inoltre, si potrebbe voler esaminare contorta, che ha risolto un sacco di questi problemi già.

Quali sono i problemi? Beh, per esempio, è probabile che desidera un'opzione presa SO_REUSEADDR.

Altri suggerimenti

oggetto Request gestore viene creato per ogni nuova richiesta. Quindi devi memorizzare flag "fatto" di server, non gestore. Qualcosa di simile a quanto segue:

class EchoServer(SocketServer.BaseRequestHandler):
    ...
    def setDone(self):
        self.server.setDone() # or even better directly self.server.shutdown()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top