Python Recv() stalling

我只是一个虾纸丫 提交于 2019-12-25 02:03:45

问题


I'm writing a very basic HTTP client:

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. I'm not sure what's wrong with my code, any help would be greatly appreciated.

Thanks!


回答1:


You do an HTTP/1.1 request which implicitly means keep-alive, e.g. the server can keep the connection open after the request is done to get more requests on the same connection. In this case the server decides after 10 seconds that it will not wait for more requests, other servers might wait longer. 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'. 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.




回答2:


As explained by Steffen, this is due to the keep-alive. For example, if you test it with google.com, you will wait for a very long time. 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.



来源:https://stackoverflow.com/questions/21342043/python-recv-stalling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!