15

从堆栈溢出的其他帖子中,这应该可以工作

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                 

s.connect(("www.cnn.com" , 80))
s.sendall("GET / HTTP/1.1\r\n")
print s.recv(4096)
s.close

但由于某种原因,它只是挂起(at recv)并且从不打印。我知道对 www.cnn.com 的请求会对其数据进行分块,但我至少应该从中读取一些内容recv,对吗?

ps 我知道这不是最好的方法,而且那里有类似的图书馆httpliburllib2但我不能将它们用于这个项目(它是给学校的)。我必须使用socket图书馆

4

6 回答 6

24

您忘记在请求行之后发送空白行:

s.sendall("GET / HTTP/1.1\r\n\r\n")

此外,HTTP 1.1 指定您应该添加Host标题字段,如HTTP 1.1 RFC 的 Host 部分中所述

s.sendall("GET / HTTP/1.1\r\nHost: www.cnn.com\r\n\r\n")
于 2015-12-10T01:20:31.263 回答
8

您的代码几乎是正确的,但您需要发送 2 个\r\n序列以满足 HTTP 协议。

一个有效的 GET 请求将如下所示(注意 2 行):

获取/HTTP/1.1

所以你的代码应该是:

s.sendall('GET / HTTP/1.1\r\n\r\n')

此外,有效的 HTTP 1.1 请求还需要额外的标头,例如Host:. 您需要将它们添加到您的请求中,如下所示:

s.sendall('''GET / HTTP/1.1
Host: cnn.com

''')
于 2015-12-10T01:21:49.023 回答
6

很抱歉浪费大家的时间。我刚刚在 Stack Overflow 上找到了这个解决方案只是在我的谷歌搜索中进行了一些改写才能找到)

import socket
request = b"GET / HTTP/1.1\nHost: www.cnn.com\n\n"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("cnn.com", 80))
s.send(request)
result = s.recv(10000)
while (len(result) > 0):
    print(result)
    result = s.recv(10000)

所有关于结局的答案都是正确的,\r\n\r\n但是那些返回的301状态。该解决方案似乎以某种方式遵循重定向?无论如何,这个解决方案对我有用

于 2015-12-10T01:24:55.373 回答
4

我正在清理 Python 3 的示例。我们需要字节/字符串转换,我们还可以使用自动关闭连接with

#!/usr/bin/env python3

import socket

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:

    s.connect(("example.com" , 80))
    s.sendall(b"GET / HTTP/1.1\r\nHost: example.com\r\nAccept: text/html\r\n\r\n")
    print(str(s.recv(4096), 'utf-8'))
于 2019-09-06T09:00:42.907 回答
2

@james:您在那里进行了 SlowLoris 攻击而没有意识到。我无法比这里更好地解释,https://www.youtube.com/watch?v=XiFkyR35v2Y 我假设您从上述所有答案中找到了解决方案,但我只是回答让您了解这一点。:)

于 2019-12-04T13:27:24.610 回答
1

尝试替换这一行:

s.sendall("GET / HTTP/1.1\r\n")

和:

s.sendall("GET / HTTP/1.1\r\n\r\n")
                             ^^^^

另外,我认为您需要替换s.close为,s.close()因为它是一个功能。

于 2015-12-10T01:21:16.747 回答