即使在 select() returns 具有可读服务器套接字之后,客户端上的 SSL_read() 也会阻塞

SSL_read() on client blocks even after select() returns with readable server socket

我正在使用 C 构建 TLS 客户端,以使用 TLS 1.3 连接到安全服务器。

我创建了一个阻塞(常规)TCP socket.And 然后连接到远程安全服务器。我还创建并配置了 SSL 上下文并将服务器套接字链接到 SSL 对象 (SSL_set_fd())。我的 SSL_connect() 成功了,我能够 send/receive 来自远程服务器的数据。

我面临的问题是,我有一个事件循环,我在其中执行多个 SSL_write() 并有一个 select() 来监视套接字以获取来自服务器的传入数据。但是,在事件循环的每次迭代中,select() returns 可读套接字和 SSL_read() 块。

为什么他 SSL_read(( 无法读取,即使 select() 标记套接字已准备好读取?

因为套接字收到了一些用于 OpenSSL 的字节,而不是给你的。就像重新谈判或心跳一样。

因为您使用的是阻塞套接字,OpenSSL 知道您不希望 SSL_read 到 return,直到它为您接收到一些数据。

如果你想要 SSL_read 到 return 即使它没有任何数据给你,那么首先要让套接字成为非阻塞的。

select 不反映 TLS 级别的数据可用性。可能是可以从套接字读取数据,但这根本不是有效负载,而是会话票证(TLS 1.3 的新功能)或警报。或者它可能是有效载荷,但不是完整的 TLS 帧 - 在这种情况下 SSL_read 还不能 return 任何数据。类似的可能是 select 声称无法读取任何内容,但 SSL_read 实际上会成功 - 因为最后一个 TLS 帧中仍有未读取的数据(检查 SSL_pending)。