我在Python中有一个需要使用TLS的HTTP客户端。我不仅需要
建立加密连接,但也从中检索信息
远程机器,例如证书颁发者。我需要做
连接到许多HTTP服务器,通常表现不佳,所以我绝对
需要暂停。使用非TLS连接,
mysocket.settimeout(5)
做我想做的事。
在众多TLS Python模块中:
python-gnutls不允许在套接字上使用settimeout(),因为 它使用非阻塞套接字:
gnutls.errors.OperationWouldBlock: Function was interrupted.
python-openssl也有类似的问题:
OpenSSL.SSL.WantReadError
标准库的SSL module不适用于Python 2.5。
TLSlite等其他库显然无法访问 证书的元数据。
程序是线程化的,所以我不能使用信号。我需要详细说明 控制HTTP对话框,所以我不能使用像urllib2这样的标准库。
背景:这是 调查项目DNSwitness。相关的SO主题:Timeout on a Python function call和How to limit execution time of a function call in Python。
答案 0 :(得分:1)
虽然我从未将其用于此目的,Twisted应该做你想要的。唯一的缺点是它是一个相当大的库,你还需要安装PyOpenSSL(Twisted取决于它)。如果你之前从未使用过,那么Twisted基于回调的架构可能会让你习惯(你真的希望在开始之前阅读教程)。
除此之外,它是围绕管理大量连接的想法而设计的,当然它允许您指定超时,重新连接等,并且您可以检索证书信息(请参阅here)。
答案 1 :(得分:1)
我假设您遇到的问题如下,您正在使用PyOpenSSL打开连接,并且您总是遇到WantReadError异常。而你无法区分这个错误和超时。请考虑以下示例:
#!/usr/bin/python
import OpenSSL
import socket
import struct
context = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
connection = OpenSSL.SSL.Connection(context,s)
connection.connect(("www.gmail.com",443))
# Put the socket in blocking mode
connection.setblocking(1)
# Set the timeout using the setsockopt
tv = struct.pack('ii', int(6), int(0))
connection.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, tv)
print "Connected to " , connection.getpeername()
print "Sate " , connection.state_string()
while True:
try:
connection.do_handshake()
break
except OpenSSL.SSL.WantReadError:
print "Exception"
pass
print "Sate " , connection.state_string()
print connection.send("koekoek\r\n")
while True:
try:
recvstr = connection.recv(1024)
break
except OpenSSL.SSL.WantReadError:
print "Exception"
pass
print recvstr
这将打开与gmail的SSL连接,发送无效字符串,读取响应并打印它。注意: *连接明确设置为阻塞模式 * recv超时在这种情况下明确设置为6秒。
现在行为是什么,当超时发生时,WantReadError异常将是thornw,在这种情况下等待6秒后。 (你可以删除while,以避免重试,但在这种情况下,我添加它们进行测试)。套接字上设置的超时似乎仅在connect()调用中有效。
另一种方法是将套接字保持在非阻塞模式,这可能适用于GNUTLS情况,也就是自己执行计时,你得到启动呼叫的时间,并且在while时,尝试:除了WantReadError,你每次都要进行检查,看看你是否还没有等待太长时间。
答案 2 :(得分:0)
答案 3 :(得分:0)
一个简单的解决方案可能是根据操作更改套接字类型。我用gnutls对它进行了测试,结果很有效: