2013-06-29 2 views
0

내 웹 사이트 호스팅을위한 작은 파이썬 웹 서버 스크립트가 있으며 요청 처리와 오류 반환으로 완료됩니다. 이 스크립트는 내 PC에서 완벽하게 작동했지만 나무 딸기 파이에서 시도해 보았을 때 매 3 분마다 다시 시작하지 않았습니다 (서버가 15 일 후에 중단되므로 매 3 분마다 다시 시작하는 것이 좋을 듯 함).재미있는 오류가있는 Python (3.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에 내 웹 사이트에 액세스 할 수 있습니다 작동), 그것은 다음과 같은 오류를 10 초마다주는 것 : 기본적으로

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) 

을 어떻게 할 이것을 고쳐라? 난 그냥 서버를 실행하는 함수를 다시 시작하는 스레딩 타이머와 간단한 함수를 사용할 수 있지만 어떻게 든 내 라스베리 파이에서 작동하지 않지만 내 창문 않습니다.

편집 : 스크립트를 처음 시작하면 웹 사이트에 액세스 할 수 있으며 빠릅니다. 10 초 후 (서버를 다시 시작한 후) 액세스 할 수 있지만 속도가 매우 느립니다. 10 초 후에 내 웹 사이트에 액세스 할 수 없습니다.

+0

글로벌 변수가 그 이유는 무엇입니까? 대신에 '서버'유형의 인스턴스 변수로 변경해야합니다. – poke

+0

@ 그것이 내가 시험해 본 것입니다. – IPDGino

+0

또한'self.status'와'httpd' 변수 모두에 커다란 동시성 문제가 있습니다. 어느 쪽도 thread safe는 아니지만, 다른 스레드 ('main'과'process')에서 그것들에 계속 액세스합니다. – poke

답변

1

서버의 기본 소켓에 직접 액세스하기 때문에 문제가 발생합니다. 소켓을 닫는 것은 효과적으로 네트워크 연결을 분리하는 것과 같습니다. 소켓 위에 앉아있는 실제 서버는 소켓이 닫혔다는 사실을 인식하지 못하고 계속 서비스를 시도합니다. 소켓이 닫힐 때, 더 이상 사용할 수있는 파일 기술자가 없습니다 (이것은 여러분이 얻는 오류입니다).

서버 연결을 끊는 대신 서버를 실제로 정상적으로 종료하도록 지시해야합니다. 이를 통해 진행중인 연결을 완료하고 백그라운드에서 수행 할 수있는 모든 작업을 안전하게 해제 할 수 있습니다. shutdown 방법을 사용하면됩니다. 실행하면 내부적으로 serve_forever 내의 루프가 발생하는 다음 번에 서버를 종료하는 것을 기억하도록 서버에 알립니다.

정확하게 기억하면 serve_forever은 차단 방법입니다. 즉, 실행될 때 계속되지 않습니다. 그래서 가장 간단한 방법 자체를 다시 시작 서버가이 일을 하나의 메인 쓰레드 될 수 있도록 :

while True: 
    httpd.serve_forever() 

를 서버가 중지-에 대한 그래서 때마다 어떤 이유-즉시 다시 시작합니다. 물론 여기에 서버를 실제로 끌 수있는 상태 변수 (True 대신)를 추가 할 것입니다. 예를 들어 KeyboardInterrupt catch의 본문에서는 먼저 해당 변수를 False으로 설정 한 다음 httpd.shutdown()을 사용하여 서버를 종료합니다.

+0

감사합니다. 나는 더 많은 문서를 읽어야 할 것으로 생각한다. – IPDGino