使用C中的OpenSSL接收http响应消息

时间:2016-07-26 17:47:04

标签: c sockets openssl httpresponse

我在尝试接收网站的http响应消息时遇到了一些问题 这是我的功能:

void Reveive_response(char *resp, SSL *ssl) {

    const int BUFFER_SIZE = 1024;
    char response[1048576];
    char *buffer = NULL;            // to read from ssl
    char *check = (char *) malloc(BUFFER_SIZE*sizeof(char));
    int bytes;                      // number of bytes actually read
    int received = 0;               // number of bytes received

    buffer = (char *) malloc(BUFFER_SIZE*sizeof(char));     // malloc
    memset(response, '\0', sizeof(response));               // response
    assign = '\0'
    do{
        memset(buffer, '\0', BUFFER_SIZE);          // empty buffer
        bytes = SSL_read(ssl, buffer, BUFFER_SIZE);
        if (bytes < 0) {
            printf("Error: Receive response\n");
            exit(0);
        }
        if (bytes == 0) break;
        received += bytes;
        printf("Received...%d bytes\n", received);
        strncat(response, buffer, bytes);   // concat buffer to response
    } while (SSL_pending(ssl));             // while pending
    response[received] = '\0';
    printf("Receive DONE\n");
    printf("Response: \n%s\n", response);
    free(buffer);
    strcpy(resp, response);                 // return via resp

}

当我调用该函数时,似乎响应消息未完成。像这样:

Received...1014 bytes
Received...1071 bytes
Receive DONE
Response: 
HTTP/1.1 200 OK
<... something else....>
Vary: Accept-Encoding
Content-Type: text/html
Conne

然后,如果我再次调用该函数,它将返回:

Received...39 bytes
Receive DONE
Response:
ction: keep-alive
Content-Length: 0

字段Connection已拆分。为什么我的功能没有收到所有的响应消息?我用while while循环里面。请告诉我哪里出错了?谢谢。

1 个答案:

答案 0 :(得分:2)

没有错。这就是TCP的工作原理。它是一种流媒体传输,它没有消息边界的概念。发送的字节数和读取的字节数之间没有1对1的关系。您的读取接收任意字节,然后您根据需要负责处理。继续阅读,缓冲和解析HTTP数据,直到您发现响应结束(有关详细信息,请参阅RFC 2616 Section 4.4 Message Length)。循环SSL_pending()是不够的(或正确)。

在这种情况下,您必须逐个读取CRLF分隔的行,直到您到达指示响应头的结尾的CRLF / CRLF对,然后您需要分析您收到的标头以了解是否有响应身体存在以及如何阅读它,因为它可能是几种不同的编码格式之一。如果存在,您可以读取正文(在进行时解码),直到达到标题指定的正文结尾。

请参阅我在my answer中发布的以下问题的伪代码:

Receiving Chunked HTTP Data With Winsock

那就是说,你真的不应该手动实现HTTP(更不用说HTTPS)了。从头开始,HTTP 是微不足道的,并且SSL / TLS也不是。在没有理解网络编程和OpenSSL编程的一些重要基础知识的情况下,您已经潜入深井。您应该使用现有的HTTP / S库,例如libcurl,并让它为您处理细节,以便您可以专注于代码的业务逻辑而不是其通信逻辑。