我正在使用 python 套接字来构建 HTTPServer,但我的 css 响应一直未决

I am using python socket to build HTTPServer, but my css response keep pending

我正在制作一个httpServer。当客户端输入localhost:8888/good.html时,他将被路由到相应的页面。

让我感到困惑的是,我的 css 响应 (res_for_style) 一直处于待处理状态。请让我知道哪里错了。

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()

我发现我可以通过在每个while循环中添加clientsocket.close()来解决它,但我仍然不知道为什么。

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

正如您已经注意到的,clientsocket.close() 将解决您的问题。

原因如下:

HTTP 使用 TCP 连接,它代表一个恒定的消息流。 HTTP 协议定义消息的结构。这种结构需要商定;否则,将无法进行有益的沟通。

消息本身分为两部分,Headers 和 body。 虽然 body 携带有效负载(HTML、CSS 或其他任何内容),但 header 包含有关以下有效负载的必要元数据。 header 的一个示例是您已经使用的 Content-Type: text/css

要知道接收到的body是否已经完全传输,接收方有两种选择: 检查接收到的 body 的长度是否与 body 预期的 body 的长度匹配,如 Content-Length header 所定义。如果 Content-Length header 丢失,则知道传输是否完成的唯一方法是检查发送方是否已关闭连接。 如果这两种情况都没有发生,则客户端认为服务器会发送更多信息并继续等待。

这就是为什么关闭套接字可以解决您的问题。

注意: HTTP 比我刚才描述的行为要复杂得多。 例如,有分块响应,其工作方式与描述的不同。更不用说keep-alive了。 有关更多参考,请参阅 this question or read the documentation

我认为构建一个简单的 HTTP 服务器是一次很棒的学习经历。 但是如果你打算在生产中使用它,我建议你使用一个框架,比如 Flask 或 Django。