我创建了一个SSL套接字(服务器端)并将套接字放入select()队列。当套接字“准备好”读取时,select()会正确返回。
然后我recv(1024)字节。在某些情况下,这将获得所有数据,而在其他情况下,它可能不会。
但是,如果套接字缓冲区中仍有数据(因为我没有全部recv()),并且我再次将同一个套接字传递给select(),它将不尽管我知道那里有数据,但仍然准备好阅读。
我想我的问题是要确认“准备好阅读”的确是从select()的角度来看,以及处理这个问题的最佳方法是什么。继续recv()直到EWOULDBLOCK似乎有点黑客,因为我正在使用select()。
我是否错误地想到了这个?我意识到我可以使用更大的recv缓冲区,但总有可能会有更多的读取而不是recv可以拉 - 所以从“select()”中处理这个的“正确”方法是什么?
提前致谢。
编辑:如评论中所述,我忽略了提到这是一个SSL服务器,显然select()在使用包裹套接字时表现不同。答案 0 :(得分:5)
recv
只关心操作系统内核视图中套接字的准备情况。那就是检查套接字是否准备好select
,只选择检查套接字缓冲区中是否有数据。但是,由于涉及用户空间缓冲,因此使用SSL会有所不同。
即使您只读取SSL套接字中的几个字节,它也需要读取包含加密数据的完整SSL记录,解密完整记录,然后它可以返回您请求的几个字节。其余数据将缓存在用户空间中以供下次读取。但是,从OS套接字缓冲区中删除了完整的SSL记录,这意味着recv
可能不会向您显示仍有可用的数据。
有两种方法可以解决这个问题。一种方法是使用pending方法查找用户空间中仍有缓冲的数据。另一种是总是recv
在大块中,这样就不会在用户空间中缓冲数据。由于SSL记录的最大大小为16k且每个recv
仅处理单个SSL记录(openssl SSL_read中的实现细节),因此始终可以调用大小为at的setTimeout(function() {
jQuery('#button').css('opacity', 1);
}, 100);
至少16384。