Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 无法获取URL正文的完整响应_Python_Sockets - Fatal编程技术网

Python 无法获取URL正文的完整响应

Python 无法获取URL正文的完整响应,python,sockets,Python,Sockets,我正在用python编写一个基本的套接字编程代码,它接受任何类型的URL并以字节为单位返回正文的内容。我只需要使用套接字库,其他什么都不用。当我传递不同的URL时,我会得到一些URL的完整响应和一些URL的部分响应。我不知道为什么会这样 这是我的代码: import socket def retrieve_url(url): url1 = url.split("http://", 1) empty = url1[1].find("/") if empty >

我正在用python编写一个基本的套接字编程代码,它接受任何类型的URL并以字节为单位返回正文的内容。我只需要使用套接字库,其他什么都不用。当我传递不同的URL时,我会得到一些URL的完整响应和一些URL的部分响应。我不知道为什么会这样

这是我的代码:

import socket


def retrieve_url(url):

    url1 = url.split("http://", 1)
    empty = url1[1].find("/")
    if empty > 0:
        url2 = url1[1].split("/", 1)
    else:
        url2 = url1[1].split("/", 1)
        url2.append('')

    soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        soc.connect((url2[0], 80))
        soc.sendall(b"GET /" + bytes(url2[1], 'utf8') + b" HTTP/1.1\r\nHost: " + bytes(url2[0],'utf8') + b"\r\nConnection: close\r\n\r\n")
        spl = soc.recv(8192)
        soc.close()
        a = spl.split(b"\r\n\r\n", 1)
        b = spl.split(None, 2)
        if b[1] == b'200':
            return a[1]
        else:
            return None
    except:
        return None


if __name__ == "__main__":
    print(retrieve_url("http://bombus.myspecies.info/node/24"))
这是我得到的输出:

b'007a84\r\n\n\n\n\n\n\n\n\n\n大黄蜂链接|熊蜂属\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
您假设所有数据都将通过单个
recv
检索。这种假设是错误的。如果您使用显式的
连接:close
,您可以依靠服务器在响应完成后关闭连接,也就是说,您应该调用
recv
,只要它返回更多数据并连接所有这些日期以获得完整响应

您还假设答案包含在响应主体中的plain中。虽然这在您的特定情况下可能是正确的,但您使用的
HTTP/1.1
使服务器也可以发送分块响应,这需要以不同的方式处理。为了避免这种情况,最好只使用
HTTP/1.0
(它还有一个隐式
连接:close

    soc.sendall(b"GET /" + bytes(url2[1], 'utf8') + b" HTTP/1.1\r\nHost: " + bytes(url2[0],'utf8') + b"\r\nConnection: close\r\n\r\n")
    spl = soc.recv(8192)
    soc.close()