SSL套接字上带有部分recv()的python select()的行为 [英] Behavior of python's select() with partial recv() on SSL socket

查看:257
本文介绍了SSL套接字上带有部分recv()的python select()的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个SSL套接字(服务器端),并将该套接字放入select()队列中.当套接字准备就绪"以供读取时,select()会正确返回.

然后我接收(1024)个字节.在某些情况下,这将获取所有数据,而在其他情况下,则可能不会.

但是,如果套接字缓冲区中仍然有数据(因为我没有全部接收recv()),而我又将该同一个套接字传递给select(),它将返回准备就绪"以进行读取,即使我知道那里有数据.

我想我的问题确实是要确认从select()的角度看,什么是准备阅读"的真正含义,以及处理该问题的最佳方法是什么.鉴于我使用的是select(),继续执行recv()直到EWOULDBLOCK似乎有点破破烂烂.

我是否错误地考虑了这一点?我意识到我可以使用更大的recv缓冲区,但是总有可能读取的内容多于recv可以提取的内容-那么处理select()的正确方法是什么? >

谢谢.

如评论中所述,我忽略了提及这是一个SSL服务器,并且在使用包装套接字时,显然select()的行为有所不同.

解决方案

select从OS内核的角度仅关心套接字的准备情况.那就是检查套接字是否已为recv准备就绪,而select仅检查套接字缓冲区中是否有数据.但是与SSL有所不同,因为涉及到用户空间缓冲.

即使您仅从SSL套接字读取了几个字节,它也需要读取包含加密数据的完整SSL记录,对完整记录进行解密,然后它可以返回您请求的几个字节.其余数据将在用户空间中缓冲,以备下次读取.但是,完整的SSL记录将从OS套接字缓冲区中删除,这意味着select可能不会向您显示仍然有可用数据.

有两种方法可以解决此问题.一种方法是使用待定方法来查找在用户空间中仍然有缓冲的数据.另一种方法是总是大块地recv,这样就不会在用户空间中缓冲任何数据.由于SSL记录的最大大小为16k,并且每个recv仅处理单个SSL记录(openssl

I then recv(1024) bytes. Under some circumstances this will get all the data, in others it may not.

However, if there is still data in the socket buffer (because I didn't recv() it all), and I pass that same socket into select() again, it will not be returned as being "ready" to read even though I know there is data there.

I suppose my question is really to confirm what "ready to be read" really means from select()'s perspective and what the best way to handle this would be. Continuing to recv() until EWOULDBLOCK seems sort of hack-ish given that I'm using select().

Am I thinking about this incorrectly? I realize I could use a larger recv buffer, but there is always the possibility that there would be more to read than recv can pull -- so what is the "right" way to handle this coming out of a select()?

Thanks in advance.

EDIT: As noted in the comments, I neglected to mention that this is an SSL server and apparently select() behaves differently when using wrapped sockets.

解决方案

select cares only about the readiness of a socket from the view of the OS kernel. That is checking if a socket is ready for recv with select only checks if there are data in the socket buffer. But with SSL it is different since user space buffering is involved.

Even if you read only a few bytes from a SSL socket it needs to read the full SSL record which contains the encrypted data, decrypt the full record and then it can return the few bytes you've requested. The rest of the data will be buffered in user space for the next read. But, the full SSL record is removed from the OS socket buffer which means that select might not show you that there are still data available.

There are two ways to work around this. One way is to use the pending method to find out of there are still data buffered in user space. The other is to always recv in huge chunks so that no data will be buffered in user space. Since the maximum size of a SSL record is 16k and each recv handles only a single SSL record (implementation detail in openssl SSL_read) it would work to always call recv with a size of at least 16384.

这篇关于SSL套接字上带有部分recv()的python select()的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆