SSL_read 当不再接收来自 HTTP 服务器的响应时卡住

问题描述 投票:0回答:1

当 HTTP 服务器完成发送信息时,即使服务器完成发送数据,SSL_read 函数也会陷入等待响应的状态。

我尝试使用 SSL 默认错误处理来检查错误,但这不起作用,因为没有错误,它只是等待响应。我尝试过使套接字成为非阻塞,但它不适用于 SSL 套接字,并且在网上找不到任何有关它的信息。我正在使用winsock2。

问题出在这里:

    do {
        bytesRead = SSL_read(ssl, buffer, sizeof(buffer) - 1);

        
        buffer[bytesRead] = '\0';
        printf("%s\n", buffer);
        sscanf_s(buffer, "HTTP/1.%*d %d", &statusCode);
        

    } while (bytesRead > 0);

这是完整的代码,稍作编辑:

int xxx() {

    WSADATA wsaData;
    SSL_CTX* sslContext = NULL;
    
    char* httpRequest = "just the request, not important"

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("Failed to initialize Winsock.\n");
        return -1;
    }

    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    sslContext = SSL_CTX_new(TLS_client_method());

    SOCKET socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (socketClient == INVALID_SOCKET)
    {
        printf("Failed to create socket.\n");
        closesocket(socketClient);
        WSACleanup();
        return -1;
    }

    struct addrinfo* result = NULL;
    if (getaddrinfo("example.com", "https", NULL, &result) != 0)
    {
        printf("Failed to resolve hostname.\n");
        closesocket(socketClient);
        WSACleanup();
        return -1;
    }

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = ((struct sockaddr_in*)result->ai_addr)->sin_addr.s_addr;
    serverAddr.sin_port = htons(443);

    freeaddrinfo(result);

    if (connect(socketClient, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        printf("Failed to connect to server.\n");
        closesocket(socketClient);
        WSACleanup();
        return -1;
    }

    SSL* ssl = SSL_new(sslContext);
    SSL_set_fd(ssl, socketClient);

    if (SSL_connect(ssl) != 1) {
        printf("SSL handshake failed.\n");
        SSL_free(ssl);
        closesocket(socketClient);
        WSACleanup();
        return -1;
    }

    if (SSL_write(ssl, httpRequest, strlen(httpRequest)) <= 0) {
        printf("Failed to send HTTP request.\n");
        SSL_free(ssl);
        closesocket(socketClient);
        WSACleanup();
        return -1;
    }

    char buffer[4096];
    int bytesRead = 0;
    int statusCode = 0;

    do {
        bytesRead = SSL_read(ssl, buffer, sizeof(buffer) - 1);
        buffer[bytesRead] = '\0';
        sscanf_s(buffer, "HTTP/1.%*d %d", &statusCode);
        

    } while (bytesRead > 0);
    

    SSL_shutdown(ssl);
    SSL_free(ssl);
    closesocket(socketClient);
    WSACleanup();

}
c windows sockets ssl https
1个回答
0
投票

阻塞套接字上的 SSL_read 将阻塞,直到底层 TCP 连接关闭、SSL 会话关闭 (SSL_shutdown) 或发生错误。当“服务器完成发送数据”时它不会关闭,因为服务器完成时套接字或 SSL 会话不知道。

使用 HTTP,客户端可以在响应完成后要求服务器关闭连接,同时添加

Connection: close
标头。但请注意,目前 HTTP 请求已完全损坏,与 HTTP 协议完全不同。

© www.soinside.com 2019 - 2024. All rights reserved.