I am making a httpServer. When the client enter localhost:8888/good.html
, he will be routed to the corresponding page.
What I get confused is that my css response(res_for_style
) keep pending. Please let me know where I got wrong.
Server.py
import socket
import json
import sys
import threading
pars = ('127.0.0.1', 8888)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(pars)
s.listen(5)
res_for_good = '''HTTP/1.1 200 OK
Content-Type: text/html
<head>
<link rel="stylesheet" href="./style.css" type="text/css">
</head>
<html>
<body>good HaHa</body>
</html>
'''
res_for_style='''HTTP/1.1 200 OK
Content-Type: text/css
body{
color: red;
}
'''
def serveClient(clientsocket, address):
while True:
data = clientsocket.recv(1024)
data_utf8=data.decode('utf-8').split('\r\n')
if '/good.html' in data_utf8[0]:
clientsocket.sendall(res_for_good.encode())
if '/style.css' in data_utf8[0]:
print("transfer css")
res="Content-Type: text/css\n\n" css_file.read()
clientsocket.sendall(res_for_style.encode())
if data == b'':
clientsocket.close()
break
while True:
(clientsocket, address) = s.accept()
threading.Thread(target = serveClient, args = (clientsocket, address)).start()
CodePudding user response:
As you have already noticed, clientsocket.close()
will solve your issue.
The reasoning behind that is as follows:
HTTP uses TCP connections, which represent a constant stream of messages. The HTTP protocol defines the structure of the messages. This structure needs to be agreed upon; otherwise, no helpful communication would be possible.
The messages themself are split into two parts, the Headers and the body.
While the body carries the payload (HTML, CSS, or whatever else), the headers contain the necessary metadata about the following payload. An example of a header would be the Content-Type: text/css
you already use.
To know if the received body has been transferred completely, the receiver has two options:
Check if the length of the received body matches the length of the body expected body, as defined by the Content-Length
header. If the Content-Length
header is missing, the only way to know if the transfer finished is by checking if the sender has closed the connection.
If neither of the two cases occurs, the client assumes that the server will send more information and keep waiting.
That's why closing the socket resolves your issue.
Note:
HTTP is way more complex than the behavior I just described.
There are, for example, chunked responses, which work in a different way than described. Not to mention keep-alive
.
For more references see this question or read the documentation.
I think it's a great learning experience to build a simple HTTP server. But I'd recommend you to use a framework, like Flask or Django, if you intend to use this in Production.
CodePudding user response:
I find that I can solve it by adding clientsocket.close()
each while loop, but I still don't know why.
def serveClient(clientsocket, address):
while True:
data = clientsocket.recv(1024)
data_utf8=data.decode('utf-8').split('\r\n')
if '/good.html' in data_utf8[0]:
clientsocket.sendall(res_for_good.encode())
if '/style.css' in data_utf8[0]:
print("transfer css")
res="Content-Type: text/css\n\n" css_file.read()
clientsocket.sendall(res_for_style.encode())
clientsocket.close() #I find that I can solve it by adding this line
if data == b'':
clientsocket.close()
break