2012-04-04 33 views
5

Tôi đã viết một máy chủ http đơn giản để xử lý yêu cầu POST:HTTP máy chủ bị treo trong khi chấp nhận các gói tin

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() 

Các máy chủ chạy tốt nhưng đôi khi nó chỉ bị treo. Khi tôi bấm CTRL +C nó mang lại cho các lỗi sau và sau đó tiếp tục dữ liệu nhận:

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 

Ai đó có thể cho tôi biết làm thế nào để khắc phục điều này? Tôi không thể hiểu được lỗi.

+0

Đó thực sự là mã bạn đang chạy? Điều đó lúng túng 'ngoại trừ:' trông giống như một lỗi cú pháp. – alberge

+0

Tôi đã bỏ lỡ câu lệnh trong khi sao chép. Xin lỗi vì điều đó. – Bruce

+0

Bạn có chắc chắn rằng khách hàng không gây ra sự cố (ví dụ: bằng cách kết nối và gửi không có gì hoặc không giới hạn số lượng dữ liệu)? – katzenversteher

Trả lời

10

tôi hoàn toàn viết lại giải pháp của tôi để sửa chữa hai nhược điểm:

  • Nó có thể đối xử với thời gian chờ ngay cả khi khách hàng đã mở chỉ một kết nối nhưng không bắt đầu giao tiếp.
  • Nếu khách hàng mở kết nối, một quy trình máy chủ mới sẽ được chia nhỏ. Một khách hàng chậm không thể chặn khác.

Nó dựa trên mã của bạn nhất có thể. Nó bây giờ là một bản demo hoàn toàn độc lập. Nếu bạn mở trình duyệt trên http://localhost:8000/ và viết 'mô phỏng lỗi' để tạo thành và nhấn gửi, nó sẽ mô phỏng lỗi thời gian chạy.

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() 

Việc chia nhánh có thể bị vô hiệu hóa, ví dụ: mục đích gỡ lỗi bằng cách xóa lớp SocketServer.ForkingMixIn khỏi mã.

+0

Câu trả lời thú vị. Tôi đã tìm được chính xác! – Bruce

+0

Tôi làm cách nào để đóng kết nối máy khách? Tôi đã cố gắng self.rfile._sock.close() nhưng nó không giúp ... Thời gian chờ bằng cách nào đó không hoạt động. Tôi muốn buộc phải đóng kết nối khi ngoại lệ xảy ra trong self.rfile.read() ... Tôi mở cho bất kỳ đề xuất nào ... – Bruce

+0

Tôi đã viết một giải pháp hoàn chỉnh thay vì lời khuyên. – hynekcer

Các vấn đề liên quan