当我使用 http1.1 协议时,为啥 style.css 文件不在同一个 TCP 连接中?
Posted
技术标签:
【中文标题】当我使用 http1.1 协议时,为啥 style.css 文件不在同一个 TCP 连接中?【英文标题】:Why the style.css file doesn't come in the same TCP connect when I use http1.1 protocol?当我使用 http1.1 协议时,为什么 style.css 文件不在同一个 TCP 连接中? 【发布时间】:2022-01-12 07:08:49 【问题描述】:我正在使用 python 套接字来编写一个持久的 http 服务器。我认为 style.css 文件应该通过相同的端口号传输,但似乎我没有得到结果。包 48 和 49 表明 style.css 与包 37 相比通过不同的端口传输。
我认为 res_for_good 的标头可能有问题。
import socket
from datetime import datetime
import threading
res_for_good = '''HTTP/1.1 200 OK\r
Date: Sun, 18 Oct 2012 10:36:20 GMT\r
Accept-Ranges: bytes\r
Content-Type: text/html; charset=iso-8859-1\r
Connection: keep-alive\r
Keep-Alive: timeout=3 max=5\r
Content-Length: 112\r
\r
<head>
<link rel="stylesheet" href="./style.css" type="text/css">
</head>
<html>
<body>good HaHa</body>
</html>
'''
res_for_notfound='''HTTP/1.1 404 Not Found\r
Date: Sun, 18 Oct 2012 10:36:20 GMT\r
Accept-Ranges: bytes\r
Content-Type: text/html; charset=iso-8859-1\r
Connection: keep-alive\r
Keep-Alive: timeout=3 max=5\r
Content-Length: 116\r
\r
<head>
<link rel="stylesheet" href="./style.css" type="text/css">
</head>
<html>
<body>404 Not Found</body>
</html>
'''
res_for_style='''HTTP/1.1 200 OK\r
Date: Sun, 18 Oct 2012 10:36:20 GMT\r
Accept-Ranges: bytes\r
Content-Type: text/css; charset=iso-8859-1\r
Keep-Alive: timeout=3 max=5\r
Connection: keep-alive\r
Content-Length: 46\r
\r
body
color: red;
font-size: 100px;
'''
def serveClient(clientsocket, address):
start = datetime.now()
objcount=0
# we need a loop to continuously receive messages from the client
while True:
objcount+=1
# then receive at most 1024 bytes message and store these bytes in a variable named 'data'
# you can set the buffer size to any value you like
data = clientsocket.recv(1024)
data_utf8=data.decode('utf-8').split('\r\n')
#data_json = json.loads(data_utf8)
print(address)
print(data)
# if the received data is not empty, then we send something back by using send() function
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()
res=res_for_style
clientsocket.sendall(res_for_style.encode())
if '/redirect.html' in data_utf8[0]:
clientsocket.sendall(res_for_redirect.encode())
elif data:
clientsocket.sendall(res_for_notfound.encode())
if data == b'':
objcount-=1
print("object count: "+str(objcount))
now = datetime.now()
# we need some condition to terminate the socket
# lets see if the client sends some termination message to the server
# if so, then the server close the socket
if objcount == max_rec_Object or (now-start).total_seconds()>waiting_time:
print(start)
print(now)
print('close socket')
clientsocket.close()
break
while True:
# accept a new client and get it's informati
# print(socket.gethostbyaddr(s.getpeername))
(clientsocket, address) = s.accept()
# create a new thread to serve this new client
# after the thread is created, it will start to execute 'target' function with arguments 'args'
threading.Thread(target = serveClient, args = (clientsocket, address)).start()
【问题讨论】:
【参考方案1】:我认为style.css文件应该通过同一个端口号传输
首先,HTTP/1.1 中没有这样的要求。然后,您的代码中存在错误。
首先是错误:从数据包捕获中可以看出,您的服务器使用 3 个 HTTP 响应来响应对 /good.html
的单个请求:一个是预期的 200,另外两个是意外的 404。第一个错误的 404 是由于这个原因代码:
if '/good.html' in data_utf8[0]:
clientsocket.sendall(res_for_good.encode())
...
if '/redirect.html' in data_utf8[0]:
clientsocket.sendall(res_for_redirect.encode())
elif data:
clientsocket.sendall(res_for_notfound.encode())
由于它在处理/good.html
后并没有停止,它最终会在最后显示的行中结束并发送res_for_notfound
。
第二个错误的404是由于这段代码:
当真时: ... 数据 = clientsocket.recv(1024) ... elif 数据: clientsocket.sendall(res_for_notfound.encode())
这里盲目假设请求不会超过 1024 并且会在单个 recv
中读取。两种假设都是错误的。从抓包可以看出,请求其实是1098字节(看ACK=1099)。即使它小于 1024,也不能保证它会在单个 recv
中被读取,这不是 TCP 的工作原理。
由于两个无关的 404 响应,客户端正确地假定服务器无法发送正确的响应,因此关闭连接以恢复正常状态。
也就是说,即使响应正确,也不能保证第二个请求是通过同一个 TCP 连接进入的。 显式或隐式宣布支持 HTTP keep alive 只是意味着客户端和服务器 支持 将 TCP 连接重用于另一个 HTTP 请求。这并不意味着特定的现有 TCP 连接必须用于下一个请求,也不意味着任何现有的 TCP 连接必须完全使用而不是创建一个新连接。
从抓包可以看出,浏览器最初打开了两个到服务器的TCP连接。这并不少见,因为通常一个站点包含许多应尽快检索的资源。只有 HTTP/1.1 只能通过单个 TCP 连接顺序而不是并行检索资源。因此,准备好另一个备用 TCP 连接是个好主意。然后,在您的情况下,这个其他已经存在的连接将用于新资源。
【讨论】:
但是为什么tcp连接在43号就关闭了。 @Ying:查看更新的回复。您的代码中不仅有错误的期望,还有实际的错误。以上是关于当我使用 http1.1 协议时,为啥 style.css 文件不在同一个 TCP 连接中?的主要内容,如果未能解决你的问题,请参考以下文章