简体   繁体   English

Python Recv()停滞不前

[英]Python Recv() stalling

I'm writing a very basic HTTP client: 我正在编写一个非常基本的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)

For some reasons, the recv() stalls for a while (~10 sec), then returns the data. 由于某些原因,recv()暂停一段时间(~10秒),然后返回数据。 I'm not sure what's wrong with my code, any help would be greatly appreciated. 我不确定我的代码有什么问题,任何帮助都会非常感激。

Thanks! 谢谢!

You do an HTTP/1.1 request which implicitly means keep-alive, eg the server can keep the connection open after the request is done to get more requests on the same connection. 您执行HTTP / 1.1请求,隐含地意味着保持活动,例如,服务器可以在请求完成后保持连接打开,以在同一连接上获得更多请求。 In this case the server decides after 10 seconds that it will not wait for more requests, other servers might wait longer. 在这种情况下,服务器在10秒后决定它不会等待更多请求,其他服务器可能会等待更长时间。 You also don't check the servers response for content-length or chunked encoded but just assume, that the server will close once the request is done. 您也不检查服务器对内容长度或分块编码的响应,但只是假设服务器将在请求完成后关闭。 This is wrong (keep-alive). 这是错误的(保持活着)。 Also, you have a proxy-connection header which does nothing, because this is not a proxy request (and proxy-connection header in itself is invalid, talking to a proxy requires a connection header). 此外,您有一个什么也不做的代理连接标头,因为这不是代理请求(并且代理连接标头本身无效,与代理通信需要连接标头)。

The easiest thing would be to issue a HTTP/1.0 request and not specifying any connection header or setting it to 'close'. 最简单的方法是发出HTTP / 1.0请求,而不指定任何连接头或将其设置为“关闭”。 Then the server will close the connection after the response is done. 然后服务器将在响应完成后关闭连接。 Also, you don't have to deal in this case with chunked encoding. 此外,您不必在这种情况下处理分块编码。

As explained by Steffen, this is due to the keep-alive. 正如Steffen所解释的那样,这是由于保持活力。 For example, if you test it with google.com, you will wait for a very long time. 例如,如果您使用google.com进行测试,则需要等待很长时间。 You can modify your code and see the timing out as follows: 您可以修改代码并查看超时,如下所示:

# 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)

In this way you wouldn't get an error. 这样你就不会出错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM