如何阅读Python socket recv

时间:2012-08-24 14:00:52

标签: python sockets

我正在尝试向网站发送HTTP请求并读取它返回的数据。我试过的第一个网站成功运作。它返回了大约4个数据包,然后返回了一个脚本捕获并终止的0数据包。

但是,尝试加载http://www.google.com/不起作用。相反,它返回大约10个相同长度的数据包,最后一个较小的数据包,然后继续超时。这种情况发生是否正常?这一切只取决于主机使用的服务器吗?

如果有人可以推荐使用socket.recv()进行读取的另一种方法,考虑到并不总是发送最终的空包,我们将不胜感激。感谢。

    try:
        data = s.recv(4096)

        while True:
            more = s.recv(4096)
            print len(more)
            if not more:
                break
            else:
                data += more
    except socket.timeout:
        errMsg = "Connection timed-out while connecting to %s. Request headers were as     follows: %s", (parsedUrl.netloc, rHeader.headerContent)
        self.logger.exception(errMsg)
        raise Exception

3 个答案:

答案 0 :(得分:3)

TCP不会为您提供“数据包”,而是从另一方发送顺序字节这是一个流recv()为您提供当前可用的流的块。您将它们拼接在一起并解析流内容。

HTTP是一个非常复杂的协议,可以手工解决,所以你可能想要从一些现有的库开始,比如httplib

答案 1 :(得分:2)

可能是Google使用Keep-Alive来保持套接字打开,以便提供进一步的请求。这将需要解析标头并读取确切的字节数。

根据您使用的HTTP版本,您必须将Connection: Keep-Alive添加到标头中。 (这可能是最简单的解决方案:只使用HTTP / 1.0而不是1.1。)

如果您仍然使用该功能,则必须收到第一批数据

  1. 解析内部是否有'\r\nContent-Length: ',如果是,则取出该字节与下一个'\r\n'之间的字节并将其转换为数字。那是你的尺寸。
  2. 如果您的数据中有'\r\n\r\n',请查看。如果是这样,那就是标题的结尾。从这里开始,您必须阅读上面提到的确切字节数。
  3. 示例:

    import socket
    s = socket.create_connection(('www.google.com', 80))
    s.send("GET / HTTP/1.1\r\n\r\n")
    x = s.recv(10000)
    poscl = x.lower().find('\r\ncontent-length: ')
    poseoh = x.find('\r\n\r\n')
    if poscl < poseoh and poscl >= 0 and poseoh >= 0:
        # found CL header
        poseocl = x.find('\r\n',poscl+17)
        cl = int(x[poscl+17:poseocl])
        realdata = x[poseoh+4:]
    

    现在,cl中的内容长度为realdata中的有效内容数据(开头)。此请求缺少的字节数为missing = cl - len(realdata)。如果是0,你就拥有了一切;如果没有,请s.read(missing)并重新计算missing,直到它为0.

    上面的代码是一个简单的工作开始;在继续之前,您可能需要进一步recv()

    这非常相似。到目前为止,更简单的方法是

    1. 在请求中使用HTTP 1.1的Connection: close标头,
    2. 使用HTTP 1.0,
    3. 使用为此任务制作的其中一个库而不是重新发明轮子。

答案 2 :(得分:2)

对于HTTP,请使用requests而不是自己编写。

> ipython

In [1]: import requests

In [2]: r = requests.get('http://www.google.com')

In [3]: r.status_code
Out[3]: 200

In [4]: r.text[:80]
Out[4]: u'<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage">'

In [5]: len(r.text)
Out[5]: 10969