Пишу небольшой сервер на python 3 с использованием модуля socket.
server.py
import socket
from views import *
URLS = {
'/': index,
'/blog': blog,
'/favicon.ico': favicon,
'/index.css': index_css
}
def generate_content(code, url):
if code == 404:
return '<h1>404</h1><p>Not found</p>'
if code == 405:
return '<h1>405</h1><p>Method not allowed</p>'
# return '<h1>{}</h1>'.format(URLS[url])
return URLS[url]()
def generate_headers(method, url):
if method != 'GET':
return ('HTTP/1.1 405 Method not allowed\r\n\r\n', 405)
if url not in URLS:
return('HTTP/1.1 404 Not found\r\n\r\n', 404)
return ('HTTP/1.1 200 OK\r\n\r\n', 200)
def parse_request(request):
parsed = request.split(' ')
method = parsed[0]
url = parsed[1]
return (method, url)
def generate_response(request):
method, url = parse_request(request)
headers, code = generate_headers(method, url)
body = generate_content(code, url)
return (headers + body).encode()
def run():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('localhost', 5000))
server_socket.listen(10)
while True:
client_socket, addr = server_socket.accept()
while True:
# client_socket, addr = server_socket.accept()
request = client_socket.recv(1024)
if not request:
break
print(request.decode('utf-8'))
print(addr)
response = generate_response(request.decode('utf-8'))
client_socket.sendall(response)
# client_socket.close()
client_socket.close()
if __name__ == '__main__':
run()
views.py
import os
dir = os.path.dirname(__file__)
def index():
with open(os.path.join(dir,'templates/index.html'), encoding='utf-8') as template:
return template.read()
def blog():
with open(os.path.join(dir,'templates/blog.html'), encoding='utf-8') as template:
return template.read()
def index_css():
with open(os.path.join(dir,'templates/index.css'), encoding='utf-8') as index_css:
return index_css.read()
def favicon():
with open(os.path.join(dir,'templates/favicon.ico')) as favicon:
return favicon.read()
Проблема внутри цикла whlie.
Если я запускаю код как есть и перехожу на localhost:5000, то завершается первая итерация внутреннего цикла while, и во время второй итерации код останавливается на получении запроса
request = client_socket.recv(1024)
. Запрос со стороны клиента есть, это видно в Chrome DevTools. Там первый запрос завершился нормально, а у второй на рассмотрении.
И на этом все. В браузере страница просто бесконечно грузится, а в консоли никаких ошибок.
Если основной код немного изменить на такой вариант:
while True:
# client_socket, addr = server_socket.accept()
while True:
client_socket, addr = server_socket.accept()
request = client_socket.recv(1024)
if not request:
break
print(request.decode('utf-8'))
print(addr)
response = generate_response(request.decode('utf-8'))
# client_socket.sendall('hello world'.encode())
client_socket.sendall(response)
client_socket.close()
# client_socket.close()
То все работает нормально, но это немного нелогично, на мой взгляд, т.к. при получении каждого нового пакета соединение с клиентом устанавливается заново.
Посмотрел
примеры в документации и там тоже не делают socket.accept() и recv() внутри одного цикла.
Так почему мой код останавливается на второй итерации на получении запроса
request = client_socket.recv(1024)
, хотя запрос отправлен?