用套接字解析 wss 协议的主机名?

Posted

技术标签:

【中文标题】用套接字解析 wss 协议的主机名?【英文标题】:Resolve host name of wss protocol with socket? 【发布时间】:2013-12-13 01:22:28 【问题描述】:

如何通过socket解析带有wss协议的主机名? 我试过这个但失败了: import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ip = socket.gethostbyname('wss://domain.tld')

【问题讨论】:

【参考方案1】:

wss://domain.tld 不是主机名,而是 URL。您无法使用套接字解析 URL,您必须将其解析为 URL 以从中获取主机名,然后您才能解决该问题。方案是 wss、http 还是 rsync 都没有关系;任何具有netloc 字段的方案都将以相同的方式工作。

例如,使用urllib.parse:

>>> from urllib.parse import urlparse # in 2.x it's from urlparse
>>> url = 'wss://domain.tld'
>>> bits = urllib.parse.urlparse(url)
>>> netloc = bits.netloc
>>> netloc
'domain.tld'

所以我们完成了,对吗?

不。 netloc 可以是主机,也可以是主机:端口。而且您不能只使用split(':'),因为 IPv6 地址中可以包含冒号——但前提是它们包含在括号中。因此,要获得netlochost 部分,您需要执行以下操作:

>>> host, _, port = netloc.rpartition(':')
>>> if ']' in port: host = netloc
>>> host
'domain.tld'

现在我们完成了,我们有一个主机名或 IP 地址,我们可以将其传递给socket.gethostbyname

但有几点需要注意。

首先,你不需要创建socket.socket对象来调用gethostbyname;它是模块上的***函数,不需要任何套接字对象。

其次,gethostbyname 不适用于 IPv6,即使在 IPv4 上也有一些限制,因此您可能希望使用 getaddrinfo 代替。

所以,结束:

>>> import socket
>>> addresses = socket.getaddrinfo(host, None) # or host, port if you prefer
gaierror: [Errno 8] nodename nor servname provided, or not known

嗯,这是意料之中的,因为我们的主机名是domain.tld,并且没有这样的域。但是,如果我们使用www.google.com,我们会得到一个包含几十个 IPv4 地址的漂亮列表,如果您的系统具有 IPv6 连接,那么还有几个 IPv6 地址。您可以只使用第一个,或者更喜欢 IPv4 而不是 IPv6,反之亦然,或者在其他一些领域进行区分。 (您还可以通过将更多参数传递给getaddrinfo,首先过滤各种字段。)

【讨论】:

我对套接字编程有点了解 :) 并且感谢您提醒我我不需要创建套接字对象。刚刚复制了...我写了一个代理服务器,现在它无法处理网络套接字。无论如何,谢谢 @SoroushKhosravi:是的,如果您想与 wss 服务器通信,您需要创建或安装 WebSocket 客户端库或 WebSocket 代理。那是一个完全不同的问题。而且 SO 不是寻求帮助选择图书馆或代理的好地方(但从 Wikipedia、here 和 here 开始,如果你想去图书馆路线,当然还有 PyPI)。

以上是关于用套接字解析 wss 协议的主机名?的主要内容,如果未能解决你的问题,请参考以下文章

https 的 WSS 连接失败

在Windows 7里,哪些字属于套接字?

使用 AWS 负载均衡器的安全 Web 套接字 (wss)

使用 Python 中的标准模块连接到 Web 套接字(wss)?

Windows套接字编程中主机名的IP地址

通过主机名连接到 Java 套接字