[英]Python's 2.7 socket.timeout behavior
下面是兩個簡單的python函數。 首先嘗試在666上連接到test.com
域(主機名有效,但端口不是)。 第二次嘗試在端口993上連接到imap.mail.outlook.com
(主機名有效,但看起來不適合公共使用/訪問)。
def fn_outlook(timeout):
try:
socket.create_connection(("imap.mail.outlook.com", 993), timeout=timeout)
except socket.timeout:
pass
def fn_test(timeout):
try:
socket.create_connection(("test.com", 666), timeout=timeout)
except socket.timeout:
pass
以下是具有不同超時的該函數的執行時間:
In [14]: %time fn_test(1)
CPU times: user 644 µs, sys: 1.07 ms, total: 1.71 ms
Wall time: 1 s
In [15]: %time fn_test(2)
CPU times: user 589 µs, sys: 1.15 ms, total: 1.74 ms
Wall time: 2 s
In [16]: %time fn_outlook(2)
CPU times: user 838 µs, sys: 2.24 ms, total: 3.08 ms
Wall time: 7.15 s
In [17]: %time fn_outlook(4)
CPU times: user 705 µs, sys: 1.18 ms, total: 1.88 ms
Wall time: 12 s
In [18]: %time fn_test(4)
CPU times: user 483 µs, sys: 795 µs, total: 1.28 ms
Wall time: 4.42 s
對於test.com
連接將在timeout
參數中指定的〜同一時間后timeout
。 但對於imap.mail.outlook.com
事情變得越來越有趣 - 套接字連接會忽略超時參數。 確切地說 - 不要忽視,而是在更長的一段時間后總是超時連接。
我可能認為此行為源自imap.mail.outlook.com
服務器,而不是來自套接字模塊。
首先,您可以將您的功能統一為:
def fn_connect(host, port, timeout):
try:
s = socket.create_connection((host, port), timeout=timeout)
except socket.timeout:
return None
else:
return s
並稱他們為:
IMAP_HOST = "imap.mail.outlook.com"
IMAP_PORT = 993
TEST_HOST = "test.com"
TEST_PORT = 666
s1 = fn_connect(IMAP_HOST, IMAP_PORT, 2)
s2 = fn_connect(TEST_HOST, TEST_PORT, 1)
#and so on....
我返回套接字以便能夠在之后正確關閉它(如果not None
)。
問題在於底層套接字機制如何解析主機名; create_connection
調用getaddrinfo ,並且對於返回的每個地址,它嘗試創建一個套接字並連接到它( 並且每個套接字都有你指定的超時 )。 那么,你的2個地址的結果:
TEST_HOST , TEST_PORT
socket.getaddrinfo("test.com", 666) [(2, 0, 0, '', ('69.172.200.235', 666))]
IMAP_HOST , IMAP_PORT
socket.getaddrinfo("imap.mail.outlook.com", 993) [(2, 0, 0, '', ('207.46.163.247', 993)), (2, 0, 0, '', ('207.46.163.138', 993)), (2, 0, 0, '', ('207.46.163.215', 993))]
如您所見,對於IMAP_HOST , IMAP_PORT,它返回3個單獨的地址(而對於TEST_HOST , TEST_PORT只返回一個)。 由於您指定它們都不起作用,它將嘗試連接到所有它們,導致一般超時〜比您指定的大3倍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.