用套接字解析 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 地址中可以包含冒号——但前提是它们包含在括号中。因此,要获得netloc
的host
部分,您需要执行以下操作:
>>> 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 协议的主机名?的主要内容,如果未能解决你的问题,请参考以下文章