Как я могу реализовать простой веб-сервер с использованием Python без использования каких-либо библиотек?
Мне нужно реализовать очень простое приложение, похожее на веб-сервер, в Python, которое будет выполнять базовые HTTP-запросы и ответы и отображать очень простой вывод на веб-странице. Я не слишком обеспокоен тем, как на самом деле кодировать его в Python, но я не уверен, с чего начать? Как это настроить? Один файл? Несколько файлов? Думаю, я понятия не имею, как подойти к тому факту, что это "сервер", поэтому я не знаю, как подходить к работе с HTTP-запросами / сокетами / запросами на обработку и т. Д. Любой совет? Ресурсы?
3 ответа
Вы можете использовать программирование сокетов для этой цели. Следующий фрагмент создает сокет tcp и прослушивает порт 9000 для запросов http:
from socket import *
def createServer():
serversocket = socket(AF_INET, SOCK_STREAM)
serversocket.bind(('localhost',9000))
serversocket.listen(5)
while(1):
(clientsocket, address) = serversocket.accept()
clientsocket.send("HTTP/1.1 200 OK\n"
+"Content-Type: text/html\n"
+"\n" # Important!
+"<html><body>Hello World</body></html>\n")
clientsocket.shutdown(SHUT_WR)
clientsocket.close()
serversocket.close()
createServer()
Запустите сервер, $ python server.py
, открыто http://localhost:9000/
в вашем веб-браузере (который действует как клиент). Затем в окне браузера вы можете увидеть текст "Hello World" (http response).
РЕДАКТИРОВАТЬ ** Предыдущий код был протестирован только на Chrome, и, как вы, ребята, предложили о других браузерах, код был изменен как:
- Чтобы сделать ответ похожим на http, вы можете отправить его в виде простого заголовка с http версия 1.1, кодом состояния 200 OK и типом содержимого text/html.
- Клиентский сокет должен быть закрыт после отправки ответа, так как это сокет TCP.
- Чтобы правильно закрыть клиентский сокет,
shutdown()
должен называться socket.shutdown против socket.close
Затем код был протестирован на Chrome, Firefox ( http://localhost:9000/) и простой curl в терминале (curl http://localhost:9000/).
Вы должны взглянуть на модуль SimpleHttpServer (py3: http.server).
В зависимости от того, что вы пытаетесь сделать, вы можете либо просто использовать его, либо проверить источник модуля ( py2, py3) для идей.
Если вы хотите получить более низкий уровень, SimpleHttpServer расширяет BaseHttpServer ( источник), чтобы он просто работал.
Если вы хотите получить еще более низкий уровень, взгляните на SocketServer (источник: py2, py3).
Люди часто будут запускать Python как python -m SimpleHttpServer
(или же python3 -m http.server
) если они просто хотят поделиться каталогом: это полнофункциональный и... простой сервер.
Я решил сделать эту работу в Python 3 и заставить его работать на Chrome в качестве примера для онлайн-курса, который я разрабатываю. Python 3 конечно нуждается encode()
а также decode()
в нужных местах. Chrome - действительно хочет отправить свой запрос GET до того, как получит данные. Я также добавил некоторые проверки ошибок, чтобы он очищал свой сокет, если вы прерываете работу сервера или он взрывается:
def createServer():
serversocket = socket(AF_INET, SOCK_STREAM)
try :
serversocket.bind(('localhost',9000))
serversocket.listen(5)
while(1):
(clientsocket, address) = serversocket.accept()
rd = clientsocket.recv(5000).decode()
pieces = rd.split("\n")
if ( len(pieces) > 0 ) : print(pieces[0])
data = "HTTP/1.1 200 OK\r\n"
data += "Content-Type: text/html; charset=utf-8\r\n"
data += "\r\n"
data += "<html><body>Hello World</body></html>\r\n\r\n"
clientsocket.sendall(data.encode())
clientsocket.shutdown(SHUT_WR)
except KeyboardInterrupt :
print("\nShutting down...\n");
except Exception as exc :
print("Error:\n");
print(exc)
serversocket.close()
print('Access http://localhost:9000')
createServer()
Сервер также распечатывает входящий HTTP-запрос. Код, конечно, отправляет только текст / html независимо от запроса - даже если браузер запрашивает значок:
$ python3 server.py
Access http://localhost:9000
GET / HTTP/1.1
GET /favicon.ico HTTP/1.1
^C
Shutting down...
Но это довольно хороший пример, который в основном показывает, почему вы хотите использовать фреймворк, такой как Flask или DJango, вместо того, чтобы писать свой собственный. Спасибо за исходный код.
Существует очень простое решение, упомянутое выше, но решение выше не работает. Это решение протестировано на хром и работает. Это Python 3, хотя он может работать на Python 2, так как я никогда не проверял его.
from socket import *
def createServer():
serversocket = socket(AF_INET, SOCK_STREAM)
serversocket.bind(('localhost',9000))
serversocket.listen(5)
while(1):
(clientsocket, address) = serversocket.accept()
clientsocket.send(bytes("HTTP/1.1 200 OK\n"
+"Content-Type: text/html\n"
+"\n" # Important!
+"<html><body>Hello World</body></html>\n",'utf-8'))
clientsocket.shutdown(SHUT_WR)
clientsocket.close()
serversocket.close()
createServer()
Это лучше, чем ответ, который был принят, но я опубликую его, чтобы будущие пользователи могли легко его использовать.