2009-10-16 6 views
1

Mon code doit essentiellement démarrer un simple serveur de discussion avec un client. Où le serveur et le client peuvent se parler entre eux. J'ai tout mis en œuvre correctement, mais je n'arrive pas à comprendre comment arrêter le serveur quand j'ai fini. (Je sais que c'est ss.shutdown()).Python Accès à BaseRequestHandler

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 SocketServerBaseRequestHandler-shutdown() chaque fois qu'il reçoit le message. Finalement, mon but est d'incorporer Tkinter pour créer une interface graphique, mais je voulais que tout le reste fonctionne, et c'est la première fois que je traite des 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 setup() est une fonction terribles en ce moment avec l'essai de prises et, mais il fonctionne pour l'instant, donc j'allait corriger plus tard.

Ma question est essentiellement: Comment puis-je mettre fin au serveur en fonction d'un message qu'il reçoit? Si possible, existe-t-il un moyen d'accéder au gestionnaire de requêtes après son démarrage?

Répondre

2

Veuillez corriger votre code pour que cela fonctionne, et inclure un moyen 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, c'est un exemple de SocketServer definition.

Veuillez inclure un exemple de la façon de démarrer/utiliser le code. Dans ce cas, pour démarrer le serveur que vous devez faire:

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 les autres threads en cours d'exécution, ce qui signifie que le serveur va quitter immédiatement.

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

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

Cependant, je ne peux pas ça fonctionne, et je pense que c'est parce que j'ai hérité des choses mal, ou que j'ai mal deviné dans ce que tu as fait.

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

De même, si vous voulez mixer une interface graphique et une programmation avec filetage, vous devriez regarder dans des exemples basés dessus. Il y a un certain nombre de hits lorsque j'ai cherché "tkinter chat". En outre, vous pourriez vouloir regarder dans tordu, qui a déjà résolu beaucoup de ces problèmes.

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

1

Un objet gestionnaire de requête est créé pour chaque nouvelle requête. Vous devez donc stocker le drapeau "done" dans le serveur, et non dans le gestionnaire. Quelque chose comme le suivant:

class EchoServer(SocketServer.BaseRequestHandler): 
    ... 
    def setDone(self): 
     self.server.setDone() # or even better directly self.server.shutdown() 
Questions connexes