Базовый веб-сервер с использованием сокетов в Python - PullRequest
0 голосов
/ 25 октября 2019

У меня есть следующий простой сервер, чтобы убедиться, что я могу получить соединение через сокет:

import socket

HOST, PORT = '', 8888

listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)
print(f'Serving HTTP on port {PORT} ...')
while True:
    print ('1 - start')
    client_connection, client_address = listen_socket.accept()
    request_data = client_connection.recv(1024)
    print(request_data.decode('utf-8'))
    client_connection.sendall(b"""HTTP/1.1 200 OK\n\nHello, World!\n""")
    client_connection.close()
    print ('2 - end')

И когда я просматриваю его в Chrome, он загружает страницу, ноне возвращает ответ. Вот что печатает сервер:

1 - start
GET / HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Sec-Fetch-Site: none
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: csrftoken=ekiwd2n8m6BjVe0Uoyif6OZ7pmWmULDs; _xsrf=2|02c4087f|7e8be522d7bb6404ace2d2117e42deed|1571691550; username-localhost-8888="2|1:0|10:1571694083|23:username-localhost-8888|44:ODk2NzY4Yzg2ZjgyNDRlMzg0ZWEwMjU1MGQ0OTU5NzE=|87587a46d228990c91d93d828c44e2a79155d03332047321e1f882dced5c67dd"; _hp2_id.1263915336=%7B%22userId%22%3A%223410356020127146%22%2C%22pageviewId%22%3A%223017774512831795%22%2C%22sessionId%22%3A%228642071851852288%22%2C%22identity%22%3Anull%2C%22trackerVersion%22%3A%224.0%22%
2 - end
1 - start

Так что, похоже, все проходит ... Но клиент (Chrome) просто получает пустой ответ:

enter image description here

Почему он не возвращает "Hello, World!"? Когда я пробую это с telnet, то тоже самое.

Обратите внимание, что это происходит с requests - только не telnet или chrome:

>>> print(requests.get('http://127.0.0.1:8888').text)
Hello, World!

Кажется, это связано с этой строкой:

request_data = client_connection.recv(1024)

1 Ответ

0 голосов
/ 25 октября 2019

Как вы сказали, проблема может быть, когда браузер отправляет более 1024 байтов.

В этом примере используется цикл while True для чтения в чанке и проверки, заканчивается ли request_data на b'\r\n\r\n' - и работает с GET, но проблема вызывает POST, которые отправляют тело сразу после b'\r\n\r\n',Чтобы решить эту проблему, я просто использую .recv(1) и проверяю b'\r\n\r\n' после каждого байта, но вы можете попытаться найти лучший способ проверить b'\r\n\r\n' в request_data

import socket

HOST, PORT = '', 8888

listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)
print(f'Serving HTTP on port {PORT} ...')
while True:
    print ('1 - start')
    client_connection, client_address = listen_socket.accept()

    request_data = b''

    while True:
        chunk = client_connection.recv(1)
        request_data += chunk
        #print(chunk)
        if request_data.endswith(b'\r\n\r\n'):
            break

    print(request_data.decode('utf-8'))

    client_connection.sendall(b"""HTTP/1.1 200 OK\n\nHello, World!\n""")
    client_connection.close()
    print ('2 - end')

Этот код читает только заголовок. Чтобы прочитать тело в POST, вы можете использовать функцию с большим значением в recv(), и POST должен отправить заголовок content-length с размером тела, чтобы было легче читать тело, чем заголовок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...