【问题标题】:Python Recv() stallingPython Recv() 停止
【发布时间】:2014-02-16 00:00:27
【问题描述】:

我正在编写一个非常基本的 HTTP 客户端:

import socket
from socket import *

Payload = """GET /test.html HTTP/1.1
Accept: */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
Accept-Encoding: gzip, deflate
Proxy-Connection: Keep-Alive
Host: example.com
Pragma: no-cache

"""

def SendAndReceive(Host, Payload):
    s = socket(AF_INET, SOCK_STREAM)
    s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    s.connect(Host)    
    s.sendall(Payload)
    tdata=[]
    while True:
        data = s.recv(1024)
        if not data: 
           break
        tdata.append(data)
    print ''.join(tdata)
    return ''.join(tdata)

SendAndReceive(("www.example.com",80),Payload)

由于某些原因,recv() 会暂停一段时间(~10 秒),然后返回数据。 我不确定我的代码有什么问题,任何帮助将不胜感激。

谢谢!

【问题讨论】:

  • 所有 HTTP 服务器或任何特定服务器都会发生这种情况吗?
  • 与所有 HTTP 服务器。这段代码一定有问题..

标签: python sockets recv buffering


【解决方案1】:

您执行 HTTP/1.1 请求,这隐含意味着保持活动状态,例如服务器可以在请求完成后保持连接打开,以便在同一连接上获取更多请求。在这种情况下,服务器会在 10 秒后决定不再等待更多请求,其他服务器可能会等待更长时间。您也不会检查服务器响应的内容长度或分块编码,而只是假设服务器将在请求完成后关闭。这是错误的(保持活动状态)。 此外,您有一个什么都不做的代理连接标头,因为这不是一个代理请求(并且代理连接标头本身是无效的,与代理交谈需要一个连接标头)。

最简单的方法是发出 HTTP/1.0 请求并且不指定任何连接标头或将其设置为“关闭”。然后服务器将在响应完成后关闭连接。此外,在这种情况下,您不必处理分块编码。

【讨论】:

  • 将 HTTP/1.1 更改为 HTTP/1.0 并保持活动以关闭解决了该问题,谢谢。快速提问,我应该如何实现实际的 recv() 缓冲?假设这个套接字对图像执行 GET。
  • @n00bz0r:好问题,糟糕的评论,为此提出一个新问题!
【解决方案2】:

正如 Steffen 所解释的,这是由于保持活动状态。例如,如果你用 google.com 测试它,你会等待很长时间。您可以修改代码并查看超时如下:

# Payload remains the same
import socket as socket_module
from socket import *
def SendAndReceive(Host, Payload):
    s = socket(AF_INET, SOCK_STREAM)
    s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    # or you could do s.setblocking(0) for timeout of 0 seconds
    s.settimeout(1)
    s.connect(Host)
    s.sendall(Payload)
    tdata=[]
    while True:
        try:
            data = s.recv(1024)
        except socket_module.error:
            # TIMEOUT
            break
        if not data:
            break
        tdata.append(data)
    print ''.join(tdata)
    return ''.join(tdata)

这样你就不会出错了。

【讨论】:

    猜你喜欢
    • 2014-08-22
    • 2018-12-21
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 2014-03-26
    相关资源
    最近更新 更多