Python Recv()停滞不前

时间:2014-01-24 20:36:56

标签: python sockets recv buffering

我正在编写一个非常基本的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秒),然后返回数据。 我不确定我的代码有什么问题,非常感谢任何帮助。

谢谢!

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

正如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)

这样你就不会收到错误。