【问题标题】:python3 sockets never stops trying to read datapython3套接字永远不会停止尝试读取数据
【发布时间】:2020-09-20 02:37:48
【问题描述】:

我正在使用 tcp 套接字从网站读取数据,确切地说是 HTTP 请求。我想使用套接字而不是请求或 pycurl,所以请不要向我推荐任何更高级别的库。

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s = wrap_socket(s)
response_bytes = b""
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
s.connect((website))
s.send(all of this works good)
#this is where my problems occur
while True:
    response_bytes+=s.recv(4096)
    if not response_bytes: break

此解决方案应该可以根据多个堆栈帖子完美运行。我想使用最有效的方式而不会超时。如果我使用 try/except 并设置套接字超时,它可以正常工作,但这不是很好的 imo。这似乎使代码永远挂起并使其尝试无限读取。它这样做有什么理由吗?

【问题讨论】:

  • 如果您想实现自己的 HTTP 处理,这远远不够。您需要阅读 RFC 2616 和后续版本,尤其是部分内容长度。我不推荐它。使用图书馆。

标签: python python-3.x sockets networking python-sockets


【解决方案1】:
s.send(all of this works good)

让我猜猜:这是一个带有显式或隐式Connection: keep-alive 的HTTP 请求。在执行 HTTP/1.1 请求时,此标头是隐式的。因此,服务器决定保持 TCP 连接打开,因为它正在等待客户端的下一个请求。

我想使用最有效的方式而不超时。

正确的方法是正确理解 HTTP 协议,从响应头中提取响应体的大小,并准确读取大小指定的数据。简单的方法是只做一个 HTTP/1.0 请求而不启用 HTTP keep-alive。在这种情况下,服务器将在响应发送后立即关闭 TCP 连接。

我想使用套接字而不是请求或 pycurl,所以请不要向我推荐任何更高级别的库。

看起来您想自己实现 HTTP。在这种情况下,您应该阅读一个标准,该标准描述了 HTTP 相当复杂的行为。不要试图猜测协议,而是阅读实际规范。

【讨论】:

  • 所以,我应该使用 1.0 并删除连接标头,而不是使用 1.1,这种方法是否可行?
  • @coke:虽然我只能推测您的代码中 all of this works good 实际上是什么,但没有 Connection 标头的简单 HTTP/1.0 请求意味着服务器应该在响应完成后立即关闭连接那种情况recv 将返回,不再读取字节。
  • @coke 不要用这个很好的建议代替阅读 HTTP 协议的文档
  • @coke: “我相信我应该保留我的尝试/除...” - 这是错误的结论。正确的结论是研究 HTTP 协议,以便确切知道必须读取多少字节。
  • @coke: “我只需要让它尽可能快” - 这就是为什么你不应该自己运行。主要的性能问题不在于本地计算,而在于网络 I/O。在同一个 TCP 连接上运行多个请求并进行内容压缩显着降低了这种开销。请求支持这两者,但您的代码不支持。当您在更简单的代码与更复杂的代码之间进行权衡时,您不会以这种方式获得更快的代码。相反,您的代码会运行得更慢,因为它没有针对问题进行优化。不,不仅仅是content-length 标头。
【解决方案2】:

这个解决方案应该可以根据多个堆栈帖子完美地工作

不,你错过了一个重要的细节。

while True:
    response_bytes+=s.recv(4096)
    if not response_bytes: break

如果response_bytes 一直非空,则它保持非空,这将成为一个无限循环。相反,做类似的事情

while True:
    buf = s.recv(2048)
    if not buf:
        break
    response_bytes+=buf

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多