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

时间:2013-12-13 01:22:29

标签: python sockets websocket

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

1 个答案:

答案 0 :(得分:3)

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地址中可以包含冒号 - 但只有当它们被括在括号中时才会有。因此,要获得host的{​​{1}}部分,您需要执行以下操作:

netloc

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

但有几个注意事项。

首先,您无需创建>>> host, _, port = netloc.rpartition(':') >>> if ']' in port: host = netloc >>> host 'domain.tld' 对象来呼叫socket.socket;它是模块的顶级函数,不需要任何套接字对象。

其次,gethostbyname不适用于IPv6,甚至在IPv4上也有一些限制,因此您可能希望改用getaddrinfo

所以,完成:

gethostbyname

嗯,这是预料之中的,因为我们的主机名是>>> 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,我们会得到一个很好的列表,其中包含几十个IPv4地址,如果您的系统具有IPv6连接,那么也可以使用几个IPv6地址。您可以只使用第一个,或者更喜欢IPv4到IPv6,反之亦然,或者在某个其他字段上进行区分。 (您还可以通过向www.google.com传递更多参数来首先过滤各种字段。)