在 python 中,如何让 UDPServer 自行关闭?
Posted
技术标签:
【中文标题】在 python 中,如何让 UDPServer 自行关闭?【英文标题】:In python, how to get a UDPServer to shutdown itself? 【发布时间】:2011-07-07 21:42:21 【问题描述】:我用声明为服务器创建了一个类:
class myServer(socketserver.BaseRequestHandler):
def handle(self):
pass
并开始于:
someServer = socketserver.UDPServer((HOST, PORT), myServer)
someServer.serve_forever()
我的问题是:如何让服务器自行关闭?我已经看到它有一个名为 BaseServer 的(基类的)基类,带有一个关闭方法。它可以在 someServer
和 someServer.shutdown()
上调用,但这来自服务器本身的外部。
【问题讨论】:
【参考方案1】:服务器实例在处理程序类中以self.server
的形式提供。所以你可以在handle
方法中调用self.server.shutdown()
。
【讨论】:
听起来不错。太糟糕了,我的截止日期已经过去了,但我仍然尝试使用print("before")
、self.server.shutdown()
和 print("after")
,但由于某种原因它没有通过 shutdown
命令。
这对我也不起作用。程序在 windows 上死锁(不能 Control+C 出来,必须 Control+Break 出来)。似乎 server.shutdown() 不能从 RequestHandler 中调用。我的猜测是关机等待所有请求完成。请求处理程序中的那段代码等待服务器关闭。瞬间僵局。使用线程延迟一点,然后调用“server.shutdown()”就可以了。凌乱,但也许有必要?
shutdown()
方法的文档字符串说 停止 serve_forever 循环。阻塞直到循环结束。这必须在 serve_forever() 在另一个线程中运行时调用,否则会死锁。参见 SocketServer.py 文件中的source。【参考方案2】:
通过使用线程。由一个线程服务并在超时后通过另一个线程。 考虑这个工作示例。为您的 UDPServer 修改它
import threading
import time
import SimpleHTTPServer
import SocketServer
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
def worker():
# minimal web server. serves files relative to the
print "serving at port", PORT
httpd.serve_forever()
def my_service():
time.sleep(3)
print "I am going down"
httpd.shutdown()
h = threading.Thread(name='httpd', target=worker)
t = threading.Thread(name='timer', target=my_service)
h.start()
t.start()
【讨论】:
雅各布 - 为什么不呢?这确实符合他的目的。 似乎是正确的,但我无法在我剩下的短时间内使用它。我应该早点问这个问题,而不是把头撞在墙上尝试不同的事情。 @Jakob,线程解决方案有效。我还没有找到另一个。你有一个工作的非线程示例吗?【参考方案3】:你可以使用扭曲的。它是关于 python 的最佳网络库,这里是一个 UDP 服务器的例子,这里是(取自扭曲的文档)有史以来最简单的 UDP 服务器;
#!/usr/bin/env python
# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
# See LICENSE for details.
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
# Here's a UDP version of the simplest possible protocol
class EchoUDP(DatagramProtocol):
def datagramReceived(self, datagram, address):
self.transport.write(datagram, address)
def main():
reactor.listenUDP(8000, EchoUDP())
reactor.run()
if __name__ == '__main__':
main()
当您准备好或发生特定事件时,您可以致电 self.transport.loseConnection()
将其关闭。
【讨论】:
嗯...我应该声明我不允许使用非标准库。谢谢。 为什么你不能使用除了 stdlib 之外的任何东西? socket 是一个令人讨厌的陷阱,很多人都会掉进去。 因为这是一个关于 DNS 的计算机网络课程的作业,即使套接字编程不是作业的重点,他们仍然选择禁止使用标准库以外的任何东西。具体来说,dnslib 以及其他外部库也是如此。不管怎样,最后期限已经过去了。我希望我所做的已经足够了。 整个课程的这个作业有很多问题,所以最终我重新提交了这个,这次我实现了你的想法。有效。我稍微调整了一下并使用了acquire
和release
的锁,这样服务器可以在完成后释放锁,然后负责关闭它的线程获取锁并关闭服务器。
我想我是为了换一个答案而写的。以上是关于在 python 中,如何让 UDPServer 自行关闭?的主要内容,如果未能解决你的问题,请参考以下文章
Python——socketserver编程(客户端/服务器)