2012-04-04 6 views
5

ich einen einfachen HTTP-Server geschrieben haben, zu POST-Anfragen bearbeiten:HTTP-Server hängt, während Pakete akzeptieren

class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler): 
    def do_POST(self): 
     ctype, pdict = cgi.parse_header(self.headers.getheader('content-type')) 
     postvars = {} 
     try: 
      if ctype == 'application/x-www-form-urlencoded': 
       length = int(self.headers.getheader('content-length')) 
       postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1) 

      self.send_response(200) 
      self.send_header("Content-type", "text") 
      self.send_header("Content-length", str(len(body))) 
      self.end_headers() 
      self.wfile.write(body) 
     except: 
      print "Error" 


def httpd(handler_class=MyHandler, server_address = ('2.3.4.5', 80)): 
    try: 
     print "Server started" 
     srvr = BaseHTTPServer.HTTPServer(server_address, handler_class) 
     srvr.serve_forever() # serve_forever 
    except KeyboardInterrupt: 
     server.socket.close() 


if __name__ == "__main__": 
    httpd() 

Der Server läuft gut, aber manchmal ist es gerade hängt. Wenn ich drücke CTRL +C es gibt die folgenden Fehler und setzt dann den Empfang von Daten:

Exception happened during processing of request from ('1.1.1.2', 50928) 
Traceback (most recent call last): 
    File "/usr/lib/python2.6/SocketServer.py", line 281, in _handle_request_noblock 
    self.process_request(request, client_address) 
    File "/usr/lib/python2.6/SocketServer.py", line 307, in process_request 
    self.finish_request(request, client_address) 
    File "/usr/lib/python2.6/SocketServer.py", line 320, in finish_request 
    self.RequestHandlerClass(request, client_address, self) 
    File "/usr/lib/python2.6/SocketServer.py", line 615, in __init__ 
    self.handle() 
    File "/usr/lib/python2.6/BaseHTTPServer.py", line 329, in handle 
    self.handle_one_request() 
    File "/usr/lib/python2.6/BaseHTTPServer.py", line 312, in handle_one_request 
    self.raw_requestline = self.rfile.readline() 
    File "/usr/lib/python2.6/socket.py", line 406, in readline 
    data = self._sock.recv(self._rbufsize) 
KeyboardInterrupt 

Kann mir jemand sagen, wie dies zu korrigieren? Ich kann die Fehler nicht verstehen.

+0

Ist das wirklich der Code, den Sie ausführen? Das baumelnde 'except:' sieht wie ein Syntaxfehler aus. – alberge

+0

Ich habe die Aussage beim Kopieren verpasst. Das tut mir leid. – Bruce

+0

Sind Sie sicher, dass der Client das Problem nicht verursacht (z. B. durch Verbinden und Senden von nichts oder einer unbegrenzten Datenmenge)? – katzenversteher

Antwort

10

Ich schrieb meine Lösung vollständig um zwei Nachteile zu beheben:

  • Es Timeout behandeln kann, auch wenn Client nur eine Verbindung geöffnet hat, aber kommunizieren nicht gestartet.
  • Wenn der Client eine Verbindung öffnet, wird ein neuer Serverprozess gegabelt. Ein langsamer Client kann andere nicht blockieren.

Es basiert auf Ihrem Code so weit wie möglich. Es ist jetzt eine komplette unabhängige Demo. Wenn Sie einen Browser unter http://localhost:8000/ öffnen und 'simulate error' in formular schreiben und auf submit drücken, wird der Laufzeitfehler simuliert.

import BaseHTTPServer 
import SocketServer 
import cgi 


class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler): 
    def do_POST(self): 
     ctype, pdict = cgi.parse_header(self.headers.getheader('content-type')) 
     postvars = {} 
     try: 
      if ctype == 'application/x-www-form-urlencoded': 
       length = int(self.headers.getheader('content-length')) 
       postvars = cgi.parse_qs(self.rfile.read(length), 
         keep_blank_values=1) 
       assert postvars.get('foo', '') != ['simulate error'] 
      body = 'Something' 
      self.send_response(200) 
      self.send_header("Content-type", "text") 
      self.send_header("Content-length", str(len(body))) 
      self.end_headers() 
      self.wfile.write(body) 
     except: 
      self.send_error(500) 
      raise 

    def do_GET(self): 
     # demo for testing POST by web browser - without valid html 
     body = 'Something\n<form method="post" action="http://%s:%d/">\n' \ 
       '<input name="foo" type="text"><input type="submit"></form>\n'\ 
       % self.server.server_address 
     self.send_response(200) 
     self.send_header("Content-type", "text/html") 
     self.send_header("Content-length", str(len(body))) 
     self.end_headers() 
     self.wfile.write(body) 


class ForkingHTTPServer(SocketServer.ForkingMixIn, BaseHTTPServer.HTTPServer): 
    def finish_request(self, request, client_address): 
     request.settimeout(30) 
     # "super" can not be used because BaseServer is not created from object 
     BaseHTTPServer.HTTPServer.finish_request(self, request, client_address) 


def httpd(handler_class=MyHandler, server_address=('localhost', 8000)): 
    try: 
     print "Server started" 
     srvr = ForkingHTTPServer(server_address, handler_class) 
     srvr.serve_forever() # serve_forever 
    except KeyboardInterrupt: 
     srvr.socket.close() 

if __name__ == "__main__": 
    httpd() 

Die Gabelung kann für z.B. Debugging-Zwecke durch Entfernen der Klasse SocketServer.ForkingMixIn aus dem Code.

+0

Super Antwort. Ich habe genau das gesucht! – Bruce

+0

Wie kann ich die Clientverbindung schließen? Ich habe versucht, self.rfile._sock.close(), aber es hilft nicht ... Das Timeout funktioniert irgendwie nicht. Ich möchte die Verbindung gewaltsam schließen, wenn Ausnahme in self.rfile.read() geschieht ... Ich bin offen für irgendwelche Vorschläge ... – Bruce

+0

Ich schrieb eine komplette Lösung anstelle von Ratschlägen. – hynekcer

Verwandte Themen