对于WSAECONNREFUSED(这意味着积压已满或端口不可用,Windows套接字有一些奇怪的行为,请参阅https://stackoverflow.com/a/10308338/851737)。如果Windows检测到这些条件之一,则重试(最多)两次,间隔为0.5秒。这意味着在套接字连接尝试(http://support.microsoft.com/kb/175523/en-us)上检测WSAECONNREFUSED至少需要1秒钟。
有没有办法在不弄乱注册表值的情况下加快检测速度?我需要在单元测试中模拟拒绝套接字连接。像模拟与原始套接字的拒绝连接一样的解决方法也是可以接受的。
这是一个简单的Python脚本,演示了这个问题:
import errno
import socket
import time
PORT = 50123
def main():
s = socket.socket()
s.bind(('127.0.0.1', PORT))
s.listen(0)
client = socket.socket()
client.connect(('127.0.0.1', PORT))
client2 = socket.socket()
start = time.time()
try:
client2.connect(('127.0.0.1', PORT))
except socket.error as e:
assert e.errno == errno.WSAECONNREFUSED
print 'connection attempt took', time.time() - start
finally:
client2.close()
client.close()
s.close()
if __name__ == '__main__':
main()
答案 0 :(得分:3)
这不完全是你问的问题。但如果您仅在单元测试中需要此功能,mock库将非常有用。
import errno
import socket
import time
import mock
PORT = 50123
def connect_mock(*agrs):
raise socket.error(errno.WSAECONNREFUSED, "Testing")
def main():
s = socket.socket()
s.bind(('127.0.0.1', PORT))
s.listen(0)
client = socket.socket()
client.connect(('127.0.0.1', PORT))
client2 = socket.socket()
start = time.time()
with mock.patch('socket.socket.connect', connect_mock):
try:
client2.connect(('127.0.0.1', PORT))
print "done"
except socket.error as e:
assert e.errno == errno.WSAECONNREFUSED
print 'connection attempt took', time.time() - start
finally:
client2.close()
client.close()
s.close()
if __name__ == '__main__':
main()
答案 1 :(得分:2)
这是我的解决方案,基于dmitry-vakhrushev的answer,它正在修补连接方法更加智能化:
if sys.platform == 'win32':
n_calls = [0]
org_connect = socket.socket.connect
def refusing_connect(*args):
if n_calls[0] < 2:
n_calls[0] += 1
raise socket.error(errno.WSAECONNREFUSED, "Testing")
return org_connect(*args)
# patch socket.connect to speed up WSAECONNREFUSED detection
patcher = mock.patch('socket.socket.connect', refusing_connect)
patcher.start()
self.addCleanup(patcher.stop)