Pregunta

Mi código, básicamente, tiene que iniciar un simple servidor de chat con un cliente.Donde el servidor y el cliente puede hablar de ida y vuelta el uno al otro.He metido todo para ser implementado correctamente, pero no puedo averiguar cómo apagar el servidor cada vez que voy a hacer.(Sé que es ss.shutdown()).

Estoy queriendo terminar bien ahora se basa en una clave compartida entre los dos (algo así como "bye"), pero no sé si de alguna manera se puede enviar un mensaje a mi SocketServer de BaseRequestHandler a shutdown() cada vez que se recibe el mensaje.

Finalmente, mi objetivo es incorporar Tkinter para hacer una interfaz gráfica de usuario, pero yo quería conseguir todo lo demás a trabajar por primera vez, y esta es mi primera vez tratando con 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()

Sí, sé setup() es una terrible funcionan ahora con el esfuerzo y las capturas, pero por ahora funciona, así que iba a corregir más tarde.

Mi pregunta es básicamente:¿Cómo puedo hacer que el servidor de hecho, basado en un mensaje que se recibe?Si es posible, hay una manera de acceder a la Solicitud de Controlador después de que se inicia?

¿Fue útil?

Solución

Por favor corregir el código, de modo que funciona, y se incluyen algunas de uso.Usted necesita agregar

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

desde SocketServer en realidad no incluir esa clase (al menos en mi versión de 2,6 ni 2.7).En su lugar, es un ejemplo de la SocketServer definición.

Por favor, incluir un ejemplo de cómo iniciar/usar el código.En este caso, para iniciar el servidor que usted necesita hacer:

ss.py SERVER localhost 8001

y el cliente como

ss.py localhost 8001

Si usted hace esto, entonces usted no puede hacer server_thread.setDaemon(Verdadero) porque no hay otros hilos de ejecución, lo que significa que el servidor se cerrará inmediatamente.

Una vez hecho esto la solución es añadir una llamada (o dos) a la auto.servidor.shutdown() insdie de su EchoServer.identificador de método, como por ejemplo:

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

Sin embargo, yo no puedo conseguir que funcione, y yo creo que es porque he heredado las cosas mal, o adivinado mal en lo que hicisteis.

Lo que usted debe hacer es buscar a alguien que ha hecho un servidor de chat en Python.El uso de Google he encontrado http://www.slideshare.net/didip/socket-programming-in-python y ciertamente hay otros.

También, si se va a mezclar y la GUI del subproceso de programación, a continuación, usted debe mirar en los ejemplos basados en eso.Hay un número de éxitos cuando busqué "tkinter chat".También, usted puede ser que desee ver en el trenzado, que ha resuelto muchos de estos problemas ya.

¿Qué problemas?Así, por ejemplo, es probable que desee un SO_REUSEADDR opción de socket.

Otros consejos

Se crea

objeto controlador de solicitudes para cada nueva solicitud. Así que hay que almacenar "hecho" bandera de servidor, no manipulador. Algo parecido a lo siguiente:

class EchoServer(SocketServer.BaseRequestHandler):
    ...
    def setDone(self):
        self.server.setDone() # or even better directly self.server.shutdown()
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top