在SSL_write()期间,OpenSSL SSL_ERROR_WANT_WRITE永远不会恢复

时间:2012-12-06 19:55:14

标签: ssl openssl client-server

我有两个应用程序通过SSL互相交谈。客户端在Windows机器上运行,服务器是基于linux的应用程序。客户端在启动时向服务器发送大量数据。数据以~4000byte块的形式发送到包含30个条目的服务器。我必须发送大约50000个条目。

在传输过程中,服务器向客户端发送消息,消息大小为~4000bytes。发生这种情况后,客户端的SSL_write()开始返回SSL_ERROR_WANT_WRITE的错误。客户端休眠10ms,并使用完全相同的参数重试SSL_write,但SSL_write无限失败。随后它中止了。如果它尝试发送新消息,我会收到一个错误,指示我没有从之前发送相同的中止消息。

错误:1409F07F:SSL例程:SSL3_WRITE_PENDING:错误的写入重试“

服务器最终会终止连接,因为它没有从客户端听到60秒并重新建立新连接。这只是一个FYI,真正的问题是如何让SSL_write恢复。

如果服务器在接收期间没有发送请求,则问题就会消失。如果我将请求的大小从16K缩小到100字节,则问题不会发生。

SSL CTX MODE设置为SSL_MODE_AUTO_RETRY和SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER。

有没有人知道什么可能导致双方同时传输大量信息可能导致此失败。如果这是一个限制,除了限制从服务器发送到客户端的大小,我该怎么做才能防止它。我担心的是,如果客户没有发送任何我申请的限制,以避免这个问题是一种浪费。

在客户端,我尝试执行SSL_read以查看是否需要在写入期间读取,即使我从未收到过SSL_ERROR_PENDING_READ,但缓冲区也不是那么大。 ~1000字节。

对此有任何见解将不胜感激。

2 个答案:

答案 0 :(得分:5)

SSL_ERROR_WANT_WRITE - 只有当套接字发送给它一个EWOULDBLOCK或EAGAIN错误时,OpenSSL(我假设您正在使用OpenSSL)才会返回此错误。当发送方缓冲区已满时,套接字发送将发出EWOUDLBLOCK错误,这反过来意味着您的服务器没有读取客户端发送的消息。

所以,基本上,问题在于您的服务器没有读取发送给它的消息。您需要检查您的服务器并进行修复,这将自动修复您的客户端问题。

另外,为什么要设置选项“SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER”? SSL始终希望在发送下一条记录之前,应该完全发送它尝试发送的记录。

答案 1 :(得分:3)

事实证明,对于客户端和服务器端应用程序,读取和写入都在一个线程中处理。在如上所述的完美风暴中,客户端正在忙着写(非阻塞)。然后,服务器决定在处理其rx缓冲区之间写入一大堆自己的消息。服务器tx是阻塞调用。服务器卡住写入,使读取匮乏,缓冲区填满,我们遇到死锁情况。

默认的Windows缓冲区是8k字节,因此填充它不需要太多。

架构应该是两侧都有一个单独的线程用于rx和tx处理。作为捷径/术语修复,一旦可以增加rx缓冲区和速率限制tx端以防止死锁。