2012-12-06 53 views
2

我有两个应用程序通过SSL相互通话。客户端运行在Windows机器上,服务器是基于Linux的应用程序。客户端在启动时向服务器发送大量数据。数据以〜4000字节块的形式发送到包含30个条目的服务器。我必须发送约50000个条目。SSL_write()期间OpenSSL SSL_ERROR_WANT_WRITE不会恢复()

在传输期间,服务器向客户端发送消息,消息大小为〜4000字节。发生这种情况后,客户端的SSL_write()开始返回SSL_ERROR_WANT_WRITE的错误。客户端睡眠10ms,然后用完全相同的参数重试SSL_write,但是,SSL_write无限失败。随后它中止。如果它尝试发送一条新消息,则会显示一条错误消息,指示我不会从先前发送相同的中止消息。

错误:1409F07F:SSL例程:SSL3_WRITE_PENDING:不好写重试”

服务器最终杀死,因为它并没有从客户听到60秒,重新建立一个新的连接。这仅仅是一个参考,真正的问题是我如何才能恢复SSL_write。

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

SSL CTX MODE设置为SSL_MODE_AUTO_RETRY和SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER。

有没有人有一个想法是什么可能导致双方同时传输大量信息可能会导致此失败。如果这是一个限制,而不是限制从服务器发送到客户端的大小,我可以做些什么来防止它。我担心的是,如果客户不发送任何我申请的节流,以避免这个问题是浪费。

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

任何有关这方面的意见将不胜感激。

+0

我还有一个想法,可能是因为服务器正忙着将自己的消息发送到客户端而不是耗尽rx缓冲区,可能是因为发送其消息而使用了Windows客户端,但缓冲区已满。基本上是一个死锁场景! –

回答

3

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

所以,本质上,问题在于你的服务器不读取发送给它的消息。你需要检查你的服务器并修复它,这会自动修复你的客户端问题。

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

2

事实证明,在客户端和服务器端应用程序中,读取和写入都在一个线程中处理。如上所述,在一场完美的风暴中,客户正忙于写作(非阻塞)。然后服务器决定在处理它的rx缓冲区之间写一大堆自己的消息。服务器tx是一个阻塞呼叫。服务器陷入困境,挨饿读取,缓冲区填满,我们有一个死锁的情况。

默认的窗口缓冲区是8k字节,所以它并不需要太多来填满它。

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