Python for 循环变慢并最终挂起
我刚接触Python(就半个小时之前)并尝试写一个简单的脚本,用来列出SMTP服务器上的用户。
用户文件就是一个简单的列表,每行一个用户名。
脚本运行得很好,但每次循环的时候速度都会变慢,直到大约第14次循环时,似乎完全卡住了。没有任何错误提示,我只能按^c来停止。
有没有人能帮我解释一下这个问题呢?
谢谢,
汤姆
#!/usr/bin/python
import socket
import sys
if len(sys.argv) != 2:
print "Usage: vrfy.py <username file>"
sys.exit(0)
#open user file
file=open(sys.argv[1], 'r')
users=[x.strip() for x in file.readlines()]
file.close
#Just for debugging
print users
# Create a Socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to the Server
connect=s.connect(('192.168.13.222',25))
for x in users:
# VRFY a user
s.send('VRFY ' + x + '\r\n')
result=s.recv(1024)
print result
# Close the socket
s.close()
4 个回答
2
我在解决同样的问题时也遇到了这个情况。
我几乎可以肯定@samplebias说得对。我发现我可以通过更加“折磨”这个系统来绕过“拖延”的问题,也就是每次都拆掉再重建每个连接:
#[ ...Snip... ]
import smtplib
#[ ...Snip... ]
for USER in open(opts.USERS,'r'):
smtpserver = smtplib.SMTP(HOST,PORT)
smtpserver.ehlo()
verifyuser = smtpserver.verify(USER)
print("%s %s: %s") % (HOST.rstrip(), USER.rstrip(), verifyuser)
smtpserver.quit()
我很好奇这种特别的“猛攻”在实际环境中是否有效,但我也很确定这样做会让一些人非常不高兴。
顺便说一下,python:自带工具。
3
s.recv
这个方法会一直等待,如果你的网络连接上没有更多的数据,它就会一直卡在那里,不会继续往下执行。
所以,你需要注意自己接收了多少数据。你得提前知道这些信息,这样客户端和服务器才能达成一致,知道要接收多大的数据。
9
很可能是你的SMTP服务器在限制你的客户端连接。这是一种防止客户端失控的措施,或者是防止客户端发送大量“无用”命令的方式。从Postfix smtpd的手册中可以看到:
smtpd_junk_command_limit (normal: 100, stress: 1)
The number of junk commands (NOOP, VRFY, ETRN or RSET) that a
remote SMTP client can send before the Postfix SMTP server
starts to increment the error counter with each junk command.
当检测到一定数量的无用命令后,smtpd守护进程会在回复之前插入1秒的延迟。如果你有权限访问这个SMTP服务器,可以尝试使用strace命令,看看服务器是否在执行nanosleep系统调用。
下面是我在本地服务器上运行你的脚本时的跟踪记录。在发送了100个VRFY命令后,它开始在命令之间休眠。你的服务器可能会在大约15个无用命令后就开始限制:
nanosleep({1, 0}, 0x7fffda9a67a0) = 0
poll([{fd=9, events=POLLOUT}], 1, 300000) = 1 ([{fd=9, revents=POLLOUT}])
write(9, "252 2.0.0 pat\r\n", 15) = 15
poll([{fd=9, events=POLLIN}], 1, 300000) = 1 ([{fd=9, revents=POLLIN}])
read(9, "VRFY pat\r\n", 4096) = 10