Python HTTP Простые постоянные соединения с сервером

#python #http #persistent

#питон #http #настойчивый

Вопрос:

Я пытаюсь создать простой HTTP-сервер, который будет получать сообщения POST и предоставлять простой ответ. Я использую стандартный HTTPServer с python. Клиент подключается с помощью session (), который должен использовать постоянное соединение, но после каждого сообщения я вижу сообщение ниже в отладке, что соединение прерывается.

ИНФОРМАЦИЯ: urllib3.connectionpool: сброс разорванного соединения:

ОТЛАДКА: urllib3.connectionpool:»GET / HTTP/ 1.1″ 200 Нет

Клиент работает правильно, когда я пытаюсь использовать его с Apache, поэтому я считаю, что проблема в моей простой конфигурации сервера. Как я могу настроить простой http-сервер для работы с постоянными подключениями?

Простой серверный код Python:

 from http.server import HTTPServer, BaseHTTPRequestHandler
from io import BytesIO
import time
import datetime
import logging


class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

    def _set_response(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header("Connection", "keep-alive")
        self.send_header("keep-alive", "timeout=5, max=30")
        self.end_headers()

    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'Hello, world!')

    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        body = self.rfile.read(content_length)

        curr_time = datetime.datetime.now()
        data = ('{"msgid":"0x0002", "timestamp": "'  str(curr_time)  '", "message":"Test http response from Raspberry Pi HTTP server"}').encode()

        self.send_response(200)
        self.end_headers()
        response = BytesIO()
        #response.write(b'This is POST request. ')
        #response.write(b'Received: ')
        response.write(data)
        self.wfile.write(response.getvalue())

print("Simple HTTP Server running...")
logging.basicConfig(level=logging.DEBUG)
httpd = HTTPServer(('', 8000), SimpleHTTPRequestHandler)
httpd.serve_forever()
 

Клиентский код Python:

 #!/usr/bin/env python

# Using same TCP connection for all HTTP requests

import os
import json
import time
import datetime
import logging
import requests
from requests.auth import HTTPBasicAuth

logging.basicConfig(level=logging.DEBUG)
start_time = time.time()

def get_data(limit):
    session = requests.Session()
    url = "http://localhost:8000"

    for i in range(10):
        curr_time = datetime.datetime.now()
        data = '{"msgid":"0x0001", "timestamp": "'  str(curr_time)  '", "message":"Test http message from Raspberry Pi"}'

        print("Sending Data: "   data)

        response = session.post(url.format(limit), data)
        #response_dict = json.loads(response.text)
        print("Received Data: "   response.text)

if __name__ == "__main__":
  limit = 1
  get_data(limit)
  print("--- %s seconds ---" % (time.time() - start_time))
 

Ответ №1:

На самом деле вы не устанавливаете Connection заголовок в своем обработчике POST. Для того, чтобы постоянные соединения работали, вам также необходимо установить Content-Length заголовок в ответе, чтобы клиент знал, сколько байтов тела HTTP нужно прочитать перед повторным использованием соединения.

Попробуйте этот обработчик POST, адаптированный из вашего кода:

    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        body = self.rfile.read(content_length)

        # Process the request here and generate the entire response
        response_data = b'{"stuff": 1234}'

        # Send the response
        self.send_response(200)
        self.send_header("Connection", "keep-alive")
        self.send_header("Content-Length", str(len(response_data)))
        self.end_headers()

        # Write _exactly_ the number of bytes specified by the
        # 'Content-Length' header
        self.wfile.write(response_data)