Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的select和ssl_Python_Select_Ssl - Fatal编程技术网

python中的select和ssl

python中的select和ssl,python,select,ssl,Python,Select,Ssl,我有一个使用select.select()的服务器应用程序,现在我正试图将SSL添加到该应用程序中,但是在侦听“原始”套接字时出现以下错误: 所以我想我应该使用select中ssl.wrap_套接字返回的ssl流。这样做,它不会返回任何错误,但也不起作用-我不确定问题是什么,我做了很多研究,遇到过类似问题的帖子,但我还没有找到解决方法 非常感谢您的帮助。正如马吕斯指出的,select.select()适用于SSL套接字,我仍然不知道是什么导致了我的无声错误,但当我认为这是SSL+select()

我有一个使用select.select()的服务器应用程序,现在我正试图将SSL添加到该应用程序中,但是在侦听“原始”套接字时出现以下错误:

所以我想我应该使用select中ssl.wrap_套接字返回的ssl流。这样做,它不会返回任何错误,但也不起作用-我不确定问题是什么,我做了很多研究,遇到过类似问题的帖子,但我还没有找到解决方法


非常感谢您的帮助。

正如马吕斯指出的,select.select()适用于SSL套接字,我仍然不知道是什么导致了我的无声错误,但当我认为这是SSL+select()时,我就大发雷霆了。因此,这个问题得到了回答。

使用带有
select()
的SSL套接字并不像最初看起来那么简单。当你给它一个错误的时候,它不会抛出一个错误,如果你只是像普通的套接字一样使用它们,你迟早会遇到一些奇怪的事情

由于
select()
需要一个文件描述符,它将获得原始套接字。但是,即使原始套接字变得可读,这并不意味着您将从SSL套接字中获取数据。您需要使用非阻塞套接字(在使用
select()
时这是一个好主意),如果它抛出
SSL\u ERROR\u WANT\u READ
(SSL等效于
ewoodblock

另一个问题是,如果向另一端的连接写入2048个字节,则端上的
select()
将返回。但是,如果您只从SSL套接字读取1024个字节,则SSL套接字可能会在内部读取更多数据,并且下一个
select()
将不会返回,即使有更多数据要读取,这可能会导致连接死锁。这是因为原始套接字(即
select()
正在使用的套接字)没有任何数据,因为它已经在SSL套接字的缓冲区中

首先想到的解决方案是读取更多数据,直到读取抛出
SSL\u ERROR\u WANT\u read
,从而清空缓冲区。但是,如果另一端生成数据的速度快于您处理数据的速度,那么在该端完成生成数据之前,您的所有其他连接都将处于饥饿状态

通过调用
sslsock.pending()
,您可以看到SSL套接字包含了多少缓冲数据。因此,更好的方法是,首先对一定数量的数据执行一次读取,检查挂起数据的数量,然后对该数量的数据执行第二次读取,从而清空缓冲区而不会导致任何更多的读取

SSL_pending()
(幕后的C函数)的手册页也说明:

SSL_pending()只考虑当前正在处理的TLS/SSL记录中的字节(如果有)。如果设置了SSL对象的read_-ahead标志,则可能已读取包含更多TLS/SSL记录的附加协议字节;这些被SSL_pending()忽略

据我所知,这意味着如果设置了
read\u ahead
,则需要重复第二步,直到
SSL\u pending()
返回0。我很确定python不会设置
read_ahead
,但最好是安全的,而不是抱歉,因此我在示例代码中包含了循环

我对这一点不太熟悉,但像这样的方法应该会奏效:

# Put the SSL socket to non-blocking mode
sslsock.setblocking(0)

while True:
    r, w, e = select.select([sslsock], [], [])
    if sslsock in r:
        try:
            data = sslsock.recv(1024)
        except ssl.SSLError as e:
            # Ignore the SSL equivalent of EWOULDBLOCK, but re-raise other errors
            if e.errno != ssl.SSL_ERROR_WANT_READ:
                raise
            continue
        # No data means end of file
        if not data:
            break
        # Drain the SSL socket's internal buffer.
        # If you want to remove the loop, make sure you don't call recv()
        # with a 0 length, since that could cause a read to the raw socket.
        data_left = sslsock.pending()
        while data_left:
            data += sslsock.recv(data_left)
            data_left = sslsock.pending()
        # Process the data
        process(data)

如果您发布一个代码示例(简化为其基本核心),这会有所帮助。Python2.6
ssl
模块的文档表明,将wrap_socket()返回的套接字传递给select()应该可以工作。是的,我确实让它工作起来了,我不太确定我做错了什么,但我猜是有问题的。谢谢你的回答。
# Put the SSL socket to non-blocking mode
sslsock.setblocking(0)

while True:
    r, w, e = select.select([sslsock], [], [])
    if sslsock in r:
        try:
            data = sslsock.recv(1024)
        except ssl.SSLError as e:
            # Ignore the SSL equivalent of EWOULDBLOCK, but re-raise other errors
            if e.errno != ssl.SSL_ERROR_WANT_READ:
                raise
            continue
        # No data means end of file
        if not data:
            break
        # Drain the SSL socket's internal buffer.
        # If you want to remove the loop, make sure you don't call recv()
        # with a 0 length, since that could cause a read to the raw socket.
        data_left = sslsock.pending()
        while data_left:
            data += sslsock.recv(data_left)
            data_left = sslsock.pending()
        # Process the data
        process(data)