2

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

在该传输期间,服务器向客户端发送消息,消息大小约为 4000 字节。之后,客户端的 SSL_write() 开始返回 SSL_ERROR_WANT_WRITE 错误。客户端休眠 10 毫秒,并使用完全相同的参数重试 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 字节。

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

4

2 回答 2

5

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

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

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

于 2012-12-07T05:24:58.273 回答
3

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

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

架构应该使得双方都有一个单独的线程用于 rx 和 tx 处理。作为一个捷径/期限修复,一次可以增加 rx 缓冲区并限制 tx 端的速率以防止死锁。

于 2012-12-07T16:31:34.197 回答