Python 访问 BaseRequestHandler

发布于 2024-08-07 19:27:21 字数 5696 浏览 7 评论 0原文

我的代码基本上需要启动一个带有客户端的简单聊天服务器。服务器和客户端可以相互通信。我已经正确实现了所有内容,但我不知道如何在完成后关闭服务器。 (我知道它是ss.shutdown())。

我想根据两者之间共享的关键字立即结束(例如 "bye"),但我不知道是否可以以某种方式向我的 SocketServer 发送消息每当收到消息时,都会从BaseRequestHandlershutdown()

最终,我的目标是合并 Tkinter 来制作 GUI,但我想让其他所有东西先工作,这是我第一次在 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()

是的,我知道 setup() 现在对于 try 和 catch 来说是一个糟糕的函数,但它现在可以工作,所以我打算稍后修复它。

我的问题基本上是:如何让服务器根据收到的消息实际结束?如果可能的话,有没有办法在请求处理程序启动后访问它?

My code basically needs to start up a simple chat server with a client. Where the server and the client can talk back and forth to each other. I've gotten everything to be implemented correctly, but I can't figure out how to shut down the server whenever I'm done. (I know it's ss.shutdown()).

I'm wanting to end right now based on a keyword shared between the two (something like "bye"), but I don't know if I can somehow send a message to my SocketServer from BaseRequestHandler to shutdown() whenever it receives the message.

Eventually, my goal is to incorporate Tkinter to make a GUI, but I wanted to get everything else to work first, and this is my first time dealing with sockets 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()

Yeah, I know setup() is a terrible function right now with the try's and catches, but it works for now, so I was going to fix it later.

My question is basically: How can I get the server to actually end based on a message that it receives? If possible, is there a way to access the Request Handler after it's started?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

宫墨修音 2024-08-14 19:27:21

请修复您的代码,使其正常工作,并提供一些使用方法。您需要添加,

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

因为 SocketServer 实际上并不包含该类(至少在我的 2.6 或 2.7 版本中不包含)。相反,它是 SocketServer 定义 中的示例。

请提供有关如何启动/使用代码的示例。在这种情况下,要启动服务器,您需要执行

ss.py SERVER localhost 8001

以下操作

ss.py localhost 8001

:如果您这样做,则无法执行 server_thread.setDaemon(True) ,因为没有其他线程在运行,这意味着服务器将立即退出。

完成后,解决方案是在 EchoServer.handle 方法的内部添加一个(或两个)调用 self.server.shutdown() ,例如:

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

但是,我无法让它工作,我认为这是因为我继承了事情出错了,或者你所做的事情猜错了。

你应该做的是搜索其他用 Python 做过聊天服务器的人。使用谷歌我发现 http://www.slideshare.net/didip/socket- programming-in-python 当然还有其他的。

另外,如果您打算混合使用 GUI 和线程编程,那么您应该查看基于此的示例。当我搜索“tkinter chat”时,出现了很多点击。另外,您可能想研究一下twisted,它已经解决了很多这样的问题。

有什么问题?例如,您可能需要 SO_REUSEADDR 套接字选项。

Please fix your code so it works, and include some way to use it. You need to add

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

since SocketServer doesn't actually include that class (at least not in my version of 2.6 nor 2.7). Instead, it's an example from the SocketServer definition.

Please include an example of how to start/use the code. In this case to start the server you need to do:

ss.py SERVER localhost 8001

and the client as

ss.py localhost 8001

If you do that then you can't do server_thread.setDaemon(True) because there are no other threads running, which means the server will exit immediately.

Once that's done the solution is to add a call (or two) to self.server.shutdown() insdie of your EchoServer.handle method, like:

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

However, I can't get that to work, and I think it's because I inherited things wrong, or guessed wrong in what you did.

What you should do is search for someone else who has done a chat server in Python. Using Google I found http://www.slideshare.net/didip/socket-programming-in-python and there are certainly others.

Also, if you are going to mix GUI and threaded programming then you should look into examples based on that. There are a number of hits when I searched for "tkinter chat". Also, you might want to look into twisted, which has solved a lot of these problems already.

What problems? Well, for example, you likely want an SO_REUSEADDR socket option.

太阳公公是暖光 2024-08-14 19:27:21

为每个新请求创建请求处理程序对象。因此,您必须将“完成”标志存储在服务器中,而不是处理程序中。像下面这样:

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

Request handler object is created for each new request. So you have to store "done" flag in server, not handler. Something like the following:

class EchoServer(SocketServer.BaseRequestHandler):
    ...
    def setDone(self):
        self.server.setDone() # or even better directly self.server.shutdown()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文