当我使用此 Python 脚本向我的服务器发送请求时:
import requests as r
url = "http://localhost:8070/"
response = r.get(url=url)
它发送以下请求:
GET / HTTP/1.1
Host: localhost:8070
User-Agent: python-requests/2.27.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
如果我理解正确的话,
Connection: keep-alive
意味着我不应该关闭客户端套接字,因为客户端可以再次使用它。
但是如果我不关闭客户端套接字,Python 脚本就会卡住,直到我关闭套接字。有没有另一种方法来表明请求已完成,以便 pythons requests 理解它?
如果我尝试将请求发送到任何其他服务器,脚本几乎立即完成。我的猜测是在几毫秒后让客户端超时,例如通过使用这样的选择:
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 1000;
select_ret = select(this->_maxfds + 1, &this->_readfds, &this->_writefds, NULL, &timeout);
现在我会在 select 返回 0 后关闭客户端套接字:
if (select_ret == 0) {
close(client_socket);
}
这是一种有效的方法,还是我错过了什么?
我发送这样的回复:
char *response = "HTTP/1.1 200 Ok\r\n\r\n";
send(this->_client_socket, response, strlen(response), 0)
但这不会终止 python 脚本。执行这行代码后,python 脚本仍然挂起。只有当我关闭我身边的插座时它才会完成。
那么我如何确定是否应该关闭它呢?正如我已经说过的,我的方法是使用超时,以防没有数据从客户端写入套接字。
您对请求中
Connection: keep-alive
的理解是正确的。但是,响应中不存在 Content-Length
或 Transfer-Encoding: chunked
标头,因此客户端知道响应何时完成的唯一方法是等待服务器端关闭套接字连接。请阅读 HTTP 1.1 协议规范的RFC 2616 第 4.4 节和RFC 7230 第 3.3.3 中列出的规则。
尝试更像这样的事情:
const char *response = "HTTP/1.1 200 Ok\r\nContent-Length: 0\r\n\r\n";
send(this->_client_socket, response, strlen(response), 0)