我们已经使用 openssl 实现了 tls。从服务器下载较大数据时SSL_ERROR_SYSCALL
收到一些数据后出现错误。对于较小的文件,我没有收到此错误,可以毫无错误地下载。对于较大的文件,ERR_get_error() 显示为零。
我们正在使用 linux 和 c++ 框架。如何寻找失败的原因?失败的原因可能是什么?请提供您的建议。
SSL_ERROR_SYSCALL 表示底层 I/O 发生了一些问题(在这种情况下应该是 TCP)。因此,您可以尝试使用 errno 进行检查。
OpenSSL 帮助说:
SSL_ERROR_SYSCALL
发生了一些 I/O 错误。OpenSSL 错误队列可能包含有关错误的更多信息。如果错误队列为空(即 ERR_get_error() 返回 0),则可以使用 ret 来查找有关错误的更多信息:如果 ret == 0,则观察到违反协议的 EOF。如果 ret == -1,则底层 BIO 报告 I/O 错误(对于 Unix 系统上的套接字 I/O,请参阅 errno 了解详细信息)。
如果您查看源代码,SSL_get_error()
您会看到,SSL_ERROR_SYSCALL
只要不确定到底发生了什么,它就会返回。它基本上是“未知”情况的默认返回码。
例如,在我的情况下(使用 BIO 进行非阻塞 IO):
int buf;
const int n = SSL_read(ssl, &buf, 0);
const int err = SSL_get_error(ssl, n);
const int st = ERR_get_error();
当n
为 0 时,err
将SSL_ERROR_SYSCALL
只是因为。但是st
仍然为 0,表示没有真正的错误。SSL_read
刚刚返回 0,因为 0 字节被写入buf
.
但是,请在调用后查找errno
/WSAGetLastError()
值以获取更多详细信息。
检查是否调用了缓冲区大小为 0 的 SSL_read()。我使用 SSL_pending() 犯了以下错误:
int waitForReadFd = nBuf < bufSize;
if (waitForReadFd)
FD_SET(fd, &rfds);
// ...
// select
int doReadFd = FD_ISSET(fd, &rfds) || SSL_pending(ssl);
if (doReadFd)
n = SSL_read(ssl, buf, bufSize - nBuf);
如果nBuf == bufSize
SSL_read() 将以 0 的缓冲区大小调用,则会导致 errno == 0 的 SSL_ERROR_SYSCALL。
更改 doReadFd 检查将避免此问题:
int doReadFd = FD_ISSET(fd, &rfds) || nBuf < bufSize && SSL_pending(ssl);
我发现问题是我公司的防火墙阻止了请求。回家吧,它应该工作
该问题是由于网络连接被切断和服务器重新设置引起的。
在下载数据之前确保连接正常。
使用 vagrant 时也可以看到类似的问题。
我们在 Go 应用程序中遇到了这个错误。我们使用第三方库从 Go 连接到底层的 openssl 库。在读取数据时,第三方库正在将要读取的缓冲区/数据的长度转换为 32 位的 C.int。对于 >= 2GB 的大数据,这会导致溢出并将负值传递给 C.SSL_read 函数。在这种情况下,它引发了 SSL_ERROR_SYSCALL 错误。