SSL_read() 返回 0,SSL_get_error 返回 6。为啥在 SSL_read() 期间连接关闭?

Posted

技术标签:

【中文标题】SSL_read() 返回 0,SSL_get_error 返回 6。为啥在 SSL_read() 期间连接关闭?【英文标题】:SSL_read() returns 0 and SSL_get_error return 6. Why is connection shutdown during SSL_read()?SSL_read() 返回 0,SSL_get_error 返回 6。为什么在 SSL_read() 期间连接关闭? 【发布时间】:2022-01-07 14:30:38 【问题描述】:

我希望通过 HTTPS 从服务器下载或读取文件,我正在使用 openSSL。

我看到连接成功,但是 SSL_read() 返回 0。SSL_get_error() 返回 6,它指的是 SSL_ERROR_ZERO_RETURN 宏,这似乎是一种正常行为,但我不确定为什么连接会在某些事情发生时关闭读?这可能就是它读取 0 字节的原因?

#define CHECK_NULL(x) if ((x)==NULL) exit (1)
#define CHECK_ERR(err,s) if ((err)==-1)  perror(s); exit(1); 
#define CHECK_SSL(err) if ((err)==-1)  ERR_print_errors_fp(stderr); exit(2); 

void ServerConnectAndRcv(uint8_t *str)

    int err;
    int sd;
    struct sockaddr_in sa;
    SSL_CTX* ctx;
    SSL*     ssl;
    char*    str;
    char     buf [4096];
    const SSL_METHOD *meth;
    
    SSLeay_add_ssl_algorithms();
    meth = TLSv1_2_client_method();
    SSL_load_error_strings();
    ctx = SSL_CTX_new (meth);
    
    SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 
    
    // create a socket and connect to the server 
    sd = socket (AF_INET, SOCK_STREAM, 0);       
    CHK_ERR(sd, "socket");
    
    memset (&sa, '\0', sizeof(sa));
    sa.sin_family      = AF_INET;
    sa.sin_addr.s_addr = inet_addr (<SERVER-IP>);           /* Server IP */
    sa.sin_port        = htons     (<SERVER-PORT>);          /* Server Port number */
    
    ssl = SSL_new (ctx);                        
    CHECK_NULL(ssl);    
    
    SSL_set_fd (ssl, sd);
    
    err = SSL_connect (ssl);                     
    CHECK_SSL(err);
    
    // read from the server
    err = SSL_read (ssl, buf, sizeof(buf) - 1);                     
    CHECK_SSL(err);
    
    if (err <= 0)
    
        printf ("Error reading: %d\n", SSL_get_error(ssl, err));
    
    
    buf[err] = '\0';
    printf ("Received % bytes\n", err); // Received 0 bytes
    SSL_shutdown (ssl);  

【问题讨论】:

你说你想“通过 HTTPS”下载,但你没有实现 HTTPS,只有 TLS。许多 HTTPS(和 HTTP)服务器只能处理有限数量的客户端连接,并且连接到此类服务器而不发送 HTTP[S] 请求被用作拒绝服务攻击,因此许多此类服务器断开此类连接以防止此类攻击。另外:您也不提供 SNI 的主机名,而且当今许多 HTTPS 服务器都需要 SNI 来实现虚拟主机,尽管显然不是您使用的那个。 我不应该能够使用这种方法从服务器读取吗?我在网上看到的例子都差不多 您可以在发送适当的 HTTP 请求后读取,例如 GET、POST 等。它是 HTTP,客户端先行。 @PresidentJamesK.Polk 这就是我正在采取的方法:***.com/a/16255486/12497236 【参考方案1】:

正如其中一位评论者指出的那样,我需要发送一个 GET 请求才能接收来自服务器的响应。 我通过SSL_write()SSL_read() 发送pszResourcePath 并阅读了整个回复。

char pszRequest[100]= 0;
char pszResourcePath[]="<resourcePath>";
char pszHostAddress[]="<serverIP>";
sprintf(pszRequest, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: Keep-Alive\r\n\r\n", pszResourcePath, pszHostAddress);

【讨论】:

以上是关于SSL_read() 返回 0,SSL_get_error 返回 6。为啥在 SSL_read() 期间连接关闭?的主要内容,如果未能解决你的问题,请参考以下文章

OpenSSL 多线程读/写

OpenSSL SSL_read: Connection was reset, errno 10054

Git报错:OpenSSL SSL_read: Connection was reset, errno 10054解决

git push报错:OpenSSL SSL_read: Connection was reset

OpenSSL SSL_read: Connection was reset, errno 10054 错误解决

OpenSSL SSL_read: Connection was reset, errno 10054 错误解决