0

我有一个用于托管我自己的网站的小型 python 网络服务器脚本,包括请求处理和错误返回。该脚本在我的 PC 上运行良好,但是当我在我的树莓派上尝试时,它不会每 3 分钟重新启动一次(服务器会在 15 分钟后崩溃,所以每 3 分钟重新启动一次似乎很好)。

所以我重写了我的服务器脚本,它会检查它是第一次启动还是重新启动。我只会给你看代码。

#Handler class above here
...
...
class Server:

    global server_class, server_adress, httpd
    server_class = HTTPServer
    server_adress = ('localhost', 8080)
    httpd = server_class(server_adress, Handler)

    def __init__(self):

        self.status = False
        self.process()

    def process(self):

        print(self.status)

        process = threading.Timer(10, self.process)
        process.start()

        if self.status == True:

            httpd.socket.close()
            self.main()

        if self.status == False:

            self.main()

    def main(self):

        try:

            if self.status == False:

                print("Server online!")
                self.status = True
                httpd.serve_forever()

            if self.status == True:

                print("Server restarted!")
                httpd.serve_forever()

        except KeyboardInterrupt:

            print("Server shutting down...")
            httpd.socket.close()

    if __name__ == "__main__":
        instance = Server()

运行十秒后(它可以工作,我可以访问我的网站http://localhost:8080/index.html),它将继续每十秒给出以下错误:

File "C:\Users\myname\Dropbox\Python\Webserver\html\server.py", line 187, in main httpd.serve_forever()
File "C:\Python33\lib\socketserver.py", line 237, in serve_forever poll_interval)
File "C:\Python33\lib\socketserver.py", line 155, in _eintr_retry return func(*args)
ValueError: file descriptor cannot be a negative integer (-1)

基本上,我该如何解决这个问题?我可以使用一个带有线程计时器的简单函数来重新启动正在运行服务器的函数,但不知何故,这在我的 Raspberry Pi 上不起作用,但它在我的 Windows 上起作用。

编辑:我还应该注意,第一次启动脚本时,我可以访问该网站,而且速度很快。10秒后(服务器重新启动后),我可以访问它,但速度很慢。再过 10 秒后,我无法访问我的网站。

4

1 回答 1

1

The problem you get happens because you access the underlying socket of the server directly. Closing the socket is effectively like unplugging your network connection. The actual server that is sitting on top of the socket remains unaware of the fact that the socket was closed, and tries to continue to serve. As the socket was closed, there is no longer a file descriptor available (this is the error you get).

So instead of cutting the server off its connection, you should tell the server to actually shut down gracefully. This allows it to finish any ongoing connections and safely release everything it might do in the background. You can do that using the shutdown method. Executing that will internally tell the server to remember to shut down the next time the loop within serve_forever occurs.

If I remember correctly, serve_forever is a blocking method, meaning that it will not continue when it is executed. So the simplest way to make a server restart itself would be a single main thread doing this:

while True:
    httpd.serve_forever()

So whenever the server stops—for whatever reason—it immediately starts again. Of course here you would now add some status variable (instead of True) which allows you to actually turn off the server. For example in the body of a KeyboardInterrupt catch, you would first set that variable to False and then shut down the server using httpd.shutdown().

于 2013-06-29T16:32:56.593 回答