为什么python套接字不能解析带有http的url

dan*_*dee -1 python sockets linux http python-3.x

我的脚本基本上看起来像这样

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('http://goal.com', 80))
Run Code Online (Sandbox Code Playgroud)

我收到一个错误,像这样

Traceback (most recent call last):
  File "/home/danidee/PycharmProjects/b&h/dang.py", line 4, in <module>
    s.connect(('http://goal.com', 80))
socket.gaierror: [Errno -2] Name or service not known
Run Code Online (Sandbox Code Playgroud)

这意味着python无法解析该特定主机,

如果我删除http://并保留它goal.com或通过我的浏览器发出请求,它就没事了,脚本和浏览器不会抛出任何错误,stackoverflow上的答案之一建议删除代理我已经完成但错误没有从我试过的终端开始走了

host http://goal.com
Run Code Online (Sandbox Code Playgroud)

但它也没有解决,我猜这是我的系统配置,但我无法弄明白我已经调查过/etc/hosts,但我没有看到任何奇怪的东西.

我知道我可以做到没有http://但我想知道为什么它不会那样工作,而且如果我想指定另一个协议,如果https或ftp

对于ftp我已经看过代码,ftp.goal.com例如,它似乎工作正常,但我尝试了http,它仍然失败.

Ilj*_*ilä 7

您正在尝试使用URL连接套接字.URL是统一资源定位器,其中包含有关在何处查找资源以及如何检索资源的信息."where"部分是主机名,端口和路径,协议(http://)如何.当您在浏览器中仅键入主机名时,它将假定http作为协议.

在您的示例中,您使用socket.AF_INET参数创建套接字,这意味着它将处理IPv4系列的地址.Python套接字了解许多地址系列,并且(正如其他答案所指出的)将魔术DNS解析为混合.在这种情况下,它正在尝试连接到名为" http://goal.com " 的主机,这显然不是您想要的.

套接字本身不了解协议.您有责任通过套接字说出正确的协议.

您可能能够连接到的原因ftp.goal.com是存在一个子域ftp的goal.com.

由于您似乎正在尝试使用URL说出HTTP协议,因此我建议您查看该requests库.它就是为此而制造的.


344*_*442 5

为了回答这个问题,您需要了解TCP / IP堆栈的工作方式。顺便说一句,我将忽略OSI模型,因为在大多数现实情况下它几乎没有用。

最重要的是,我们拥有用于在物理/无线链路之间传输位和字节的协议。这包括诸如以太网,802.11,MAC之类的东西。这是从一台机器直接连接到另一台机器的直接通信。期。

然后,除此之外,我们有了协议设计的瑰宝之一,即Internet协议。与您可能想像的不同,它是一个(相对)非常简单的协议。目的是定义主机,地址,路由,服务质量和其他一些概念。这是非常简约的观点。借助IP,一台机器可以通过网络和网关(通常指路由器)的整体布置间接连接到另一台机器。

但是,知识产权本身有一定的陷阱。即...

  • 没有端口的概念。
  • 一切都必须由Internet地址表示,即没有thingslikethis.com,也称为域。
  • IP 不可靠,这意味着数据包可能会丢失(没有任何通知),重复,损坏等。这确实发生在现代网络中。根本没有“连接”的概念。只是包,期间。

因此,为解决(大多数)这些问题,在协议设计中出现了一个不太聪明的宝石,即传输控制协议。注意:为简单起见,忽略UDP。TCP的目的是允许通过不可靠的路由协议(通常为IP)建立可靠且有状态的连接。为此,这给分组增加了相当大的开销,这有时是不希望的。它还具有一些不错的附加功能,例如端口。这个想法是,端口代表在主机内部运行的“服务”或“应用程序”,以及其他应用程序。这是多任务系统的原始概念。由主机地址和端口组成的一对称为“套接字”。经过三次握手后,一对套接字(主机A中的一个指向主机B,另一个主机B中的一个指向主机A)被称为连接。多亏有了TCP,我们现在可以说诸如192.168.1.123:8080,在那里发送数据之类的东西,并确信数据永远不会到达目的地,或者成功而正确地到达目的地。但是,仍然没有域名!

进入域名系统。它定义了“域”的层次结构,符号名称表示主机或同一类型的另一层次结构。例如,我们有顶级域com及其子域google,它们恰好是指201.191.202.174。我们以的形式用点分隔的反向符号表示域google.com。使用IP加上TCP加上DNS,我们可以知道诸如之类的内容google.com:21,并获得可靠的连接。欢呼!

现在值得注意的是,当Python像大多数库/语言/操作系统一样谈论“套接字”时,它是在TCP的意义上谈论套接字。而且,正如我们已经知道的,TCP只能处理style的东西192.168.1.123:8080。但是,Python的socket.socket.connect(尽管主要是它的包装器)对C / POSIX的提供了一些抽象,connect(3)如果提供了主机名而不是实际地址,它就会与DNS进行适当的转换。尽管如此,抽象到此为止。

但是,诸如此类的时髦东西https://qwe.rty.uio/asd/fgh.html呢?要解决此问题,请输入方程式中最复杂的部分之一。超文本传输​​协议是一个广为人知的知识,但所有人都为之荣耀。HTTP在某种程度上是一种多用途的协议。在此基础上,它定义了统一资源标识符,这在大多数情况下是统一资源定位符。这样,您可以/在域后使用斜杠()来寻址其中的“资源”,例如图像或网页。URI还定义了访问资源的方式(http://表示“通过HTTP”,https://表示“通过HTTPS ”,ftp://表示“通过FTP”“,等等。)。HTTP添加了不可计数的额外时髦的东西,这些东西对于万维网(通常错误地称为“ Internet”)以其工作方式运行是必需的,例如会话,身份验证,加密,状态代码,缓存,代理,文件下载等...

tl; dr:Python的socket库是对C的精简包装,恰好添加了DNS解析先锋机制。除此之外,它还可以使用普通的TCP概念。