下面
http://marc.info/?l=openssl-users&m=124386218929227
它声明
“......这就是为什么理解任何端口上的任何可能的正向进展(以及返回WANT_READ的写操作可能已经取得进展!)都非常重要,这要求您重试所有端口上的所有挂起操作。 ......“
因此,我理解返回SSL_read()
的{{1}}可能已取得进展(即使它没有返回任何数据),我是否正确?
我有一个事件驱动的单线程应用程序,它有3个非阻塞的ssl套接字。当每个套接字完成连接时,我会读取套接字,直到我得到WANT_READ
。我的理解是WANT_READ
意味着我现在可以调用WANT_READ
并等待套接字再次准备好再次阅读。
当select()
返回时,一个循环遍历3个套接字,每个套接字调用select()
。
说Socket 1上的读取返回ssl_read()
而没有数据。
是否有可能Socket 2返回一些数据,当没有更多内容可以读取时返回WANT_READ
,现在已经取得了一些进展,因此套接字1上的读取现在可以返回数据?但由于循环已经完成了对套接字1的读取,因此不会发生。
当循环通过3个插槽时,它会在那里等待并挂起。这种情况会发生吗?
如果是这种情况,如何查看是否所有3个插座都无法取得进展? 例如,假设循环通过;
WANT_READ
。 WANT_READ
(并取得进展,使套接字1现在可以返回数据)WANT_READ
。 但基于上面的引用(任何前进进度需要重试所有挂起的操作),我应该再次重试所有套接字;所以第二次贯穿循环;
WANT_READ
WANT_READ
WANT_READ
。但是如果套接字3上的最后一次读取取得了进展,那么套接字2现在又会返回数据呢?所以我的问题是(如果我的理解是正确的),我怎么知道是否不能再取得进展呢?
编辑1:
所以我看到的是:
我的循环遍历连接到client1的所有套接字(例如,有2个套接字)
WANT_READ
返回WANT_READ ssl_read()
返回数据,ssl_read()
再次返回数据,然后ssl_read()
最终返回WANT_READ 然后当所有套接字都返回WANT_READ时,我等待ssl_read()
。但是,我的应用仍在等待客户端已发送的数据。如果我让客户端启动另一个连接(同时保持原始文件处于活动状态),请选择return,这就是我所看到的:
select()
返回数据,然后ssl_read()
再次返回WANT_READ ssl_read()
返回WANT_READ ssl_read()
返回数据,然后返回WANT_READ。因此select检测到新连接并在我的循环中运行,循环遍历所有活动连接。这次,除了套接字3上的新数据之外,它还从上次发现套接字1中的数据。所以我的理论是select()第一次没有返回,因为我在套接字上等待接收的数据1已经到达并准备好等待我调用ssl_read()。但是上次我打电话给ssl_read时,我得到了WANT_READ。
答案 0 :(得分:2)
当SSL_read()
返回负值时,您应该从SSL_get_error()
获取错误代码。如果错误代码为 SSL_ERROR_WANT_READ ,则表示您应该等待(例如使用select()
或poll
)该套接字可读(直到某些数据从网络到达)。如果发生这种情况,您应该再次在该套接字上重试SSL_read()。 您不必在您拥有的所有SSL套接字上重试SSL_read()
,仅在那些返回 SSL_ERROR_WANT_READ 的SSL套接字上重试SSL_write()
。您应该使用SSL_ERROR_WANT_WRITE
(当它返回SSL_read()
时)执行类似的事情。
但请注意,SSL_get_error()
可能会返回SSL_ERROR_WANT_WRITE
SSL_write()
而SSL_ERROR_WANT_READ
可以返回n = SSL_read()
。可能会发生这种情况,因为除了您的数据之外,SSL还需要发送/接收一些其他消息(例如,为了发送您的数据,它需要发送一些消息并首先接收响应)。
总结:
n > 0
返回时:
a)n
- &gt;您刚收到n < 0
个字节的数据
b)err = SSL_get_error()
- &gt; select()
已退回
SSL_read()
直到套接字可读并再次致电select()
SSL_read()
直到套接字可写并再次调用n = 0
c)if(SSL_get_shutdown(SSL*) & SSL_RECEIVED_SHUTDOWN)
- &gt; n = SSL_write()
:另一方干净关闭,否则shudown不干净,但SSL连接关闭你可以关闭套接字(SSL *对象也是)
n > 0
返回时:
a)n
- &gt;您刚刚发送了n < 0
个字节的数据
b)err = SSL_get_error()
- &gt; select()
已退回
SSL_write()
直到套接字可读并再次致电select()
SSL_write
直到套接字可写并再次调用n = 0
c)if((err = SSL_get_error(SSL*,err)) == SSL_ERROR_ZERO_RETURN)
- &gt; {{1}}:另一方干净关闭,否则shudown不干净,但SSL连接关闭你可以关闭套接字(SSL *对象也是)
我希望有所帮助。