2016-07-26 64 views
0

尝试接收网站的http响应消息时遇到一些问题。
这是我的函数:在C中使用OpenSSL接收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 

中的现场连接被分裂。为什么我的功能没有收到所有的回复信息?我用while循环里面。请告诉我我哪里错了?谢谢。

回答

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),并让它为您处理细节,以便您可以专注于代码的业务逻辑而不是其通信逻辑。

+0

谢谢。我会尽快回复你。 – thanhdx

+0

嗨,阅读更多信息后,我仍然有一些问题: – thanhdx

+0

- 如何阅读一行文字直到CRLF? SSL_read()按字节读取缓冲区。我应该读取字节缓冲区然后解析它来处理每一行?或者逐个读取字节直到CRLF(它可能运行得很慢)?还是其他什么? – thanhdx