【问题标题】:Python Socket Error 300 'Moved Permanently'Python 套接字错误 300 '永久移动'
【发布时间】:2018-12-05 17:21:32
【问题描述】:

我一直在尝试运行此代码以开始与不同站点的通信,但无法建立一个。有人可以帮我解决我在这里缺少的东西吗?

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

server = 'www.python.org'
port = 80 #defining port / acting like a browser

server_ip = socket.gethostbyname(server)
print(server_ip)

request = "GET / HTTPS/1.1\nHost: "+server+"\n\n"
s.connect((server_ip,port))
s.send(request.encode())
result = s.recv(4096)

while (len(result) > 0):
     print(result)
     result = s.recv(1024)

每次使用不同的网站时,我都会收到此错误消息:

<socket.socket fd=508, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>

151.101.152.223 b'HTTP/1.1 301 Moved Permanently\r\nServer: Varnish\r\nRetry-After: 0\r\nLocation: https://www.python.org/\r\nContent-Length: 0\r\nAccept-Ranges: bytes\r\nDate : 2018 年 12 月 5 日星期三 17:10:03 GMT\r\n通过:1.1 varnish\r\n连接:关闭\r\nX-Served-By: cache-bom18222-BOM\r\nX-Cache: HIT\r\ nX-Cache-Hits: 0\r\nX-Timer: S1544029803.224270,VS0,VE0\r\nStrict-Transport-Security: max-age=63072000;包括子域\r\n\r\n'

【问题讨论】:

  • 在您的代码中,您使用 80 端口与 HTTPS 协议连接。尝试使用 443(HTTPS 的默认端口)端口连接到主机。同样对于 HTTPS 连接,您必须实现 TLS 握手或使用标准库 (docs.python.org/3/library/ssl.html) 中的 TLS/SSL 包装器。

标签: python sockets


【解决方案1】:

这个请求在多个级别上是错误的:

port = 80 #defining port / acting like a browser
...
request = "GET / HTTPS/1.1\nHost: "+server+"\n\n"

没有HTTPS/1.1 协议。只有HTTP/1.1。要访问https://.. URL,您需要首先连接到该站点(默认端口 443 而不是您使用的 80)、upgrade the TCP socket to SSL 并发出正确的 HTTP 请求,即使用 HTTP/1.1 而不是 HTTPS/1.1

此外,行和标题分隔符必须是\r\n,而不仅仅是您使用的\n。但大多数服务器会忽略差异。

另外,HTTP/1.1 隐式启用持久 HTTP 连接(HTTP keep-alive)。这意味着服务器可能不会像您的代码预期的那样在响应后立即关闭连接,但可能会在同一连接中等待很长时间以获取更多请求。对于这样简单的请求,最好使用HTTP/1.0,它没有隐式保持活动,并且在其他方​​面也更简单(没有分块传输编码)。

.... b'HTTP/1.1 301 Moved Permanently ... Location: https://www.python.org/

这甚至不是错误。这是一个 HTTP 重定向,它表示您应该使用 https:// 访问该站点(您可能尝试这样做但方法错误)。

最后,您的代码可能如下所示:

import socket
import ssl

(server,port) = ('www.python.org',443)
request = "GET / HTTP/1.0\r\nHost: "+server+"\r\n\r\n"

s = socket.socket()
s.connect((server,port))
s = ssl.create_default_context().wrap_socket(s, server_hostname=server)
s.send(request.encode())

result = s.recv(4096)
while (len(result) > 0):
     print(str(result))
     result = s.recv(1024)

尽管如此,即使这段代码可以正常工作,我还是建议您使用像 requests 这样的 HTTP 库。如果您坚持编写自己的 HTTP 堆栈,那么请研究该标准 - 该协议比简单查看几个示例所暗示的要复杂得多。

【讨论】:

  • 你能向我解释一下:如何通过改变这一行; "GET / HTTPS/1.1\nHost:" 到这个; "GET / HTTP/1.0\r\n\r\nHost:" 并将端口编辑为 80 使我的代码运行。
  • @SaralJain:我不知道你说的 是什么意思...让我的代码运行..."。您的代码之前也运行过,但是由于您做错了,因此给您带来了意想不到的结果。将端口更改为 80 并将 HTTPS/1.1 更改为 HTTP/1.0 还会为我返回一个带有 www.python.org 的 301 重定向,如果它会为您返回任何其他内容,我会感到惊讶 - 但您没有提供任何详细信息。当然,在 http:// 上返回内容(而不是仅重定向到 https://)的网站现在将返回此内容,因为请求是正确的。
猜你喜欢
  • 1970-01-01
  • 2017-10-27
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
相关资源
最近更新 更多