头和HTTP服务器响应的内容之间的差异(插座) [英] Differ between header and content of http server response (sockets)

查看:124
本文介绍了头和HTTP服务器响应的内容之间的差异(插座)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道,有没有办法找出在响应流头端的可能性?

i want to know, is there a possibility to find out where in the response Stream the header ends?

问题的背景是如下,我使用在C插座从网站获得的内容,内容是EN采用gzip codeD。我想直接从流和连接code gzip的内容与zlib的阅读内容。但是,我怎么知道gzip的内容开始,HTTP头就完成了。

The background of the question is as following, i am using sockets in c to get content from a website, the content is encoded in gzip. I would like to read the content directly from stream and encode the gzip content with zlib. But how do i know the gzip content started and the http header is finished.

我大概尝试了两种方式这是给我一些,在我看来,奇怪的结果。首先,我读了整个流中,并打印出来在终端,我的HTTP头结尾为\\ r \\ n \\ r \\ n像我预期,但谢胜利的时候,我只是检索响应,一旦得到头然后读取while循环,这里头没有为\\ r \\ n \\ r \\ n结尾的内容。

I roughly tried two ways which are giving me some, in my opinion, strange results. First, i read in the whole stream, and print it out in terminal, my http header ends with "\r\n\r\n" like i expected, but the secound time, i just retrieve the response once to get the header and then read the content with while loop, here the header ends without "\r\n\r\n".

为什么呢?而这方式是在内容阅读的正确方法?

Why? And which way is the right way to read in the content?

我只给你code,所以你可以看到我应得从服务器的响应。

I'll just give you the code so you could see how i'm getting the response from server.

//first way (gives rnrn)
char *output, *output_header, *output_content, **output_result;
size_t size;
FILE *stream;
stream = open_memstream (&output, &size);
char BUF[BUFSIZ];
while(recv(socket_desc, BUF, (BUFSIZ - 1), 0) > 0)
{
    fprintf (stream, "%s", BUF);
}
fflush(stream);
fclose(stream);

output_result = str_split(output, "\r\n\r\n");
output_header = output_result[0];
output_content = output_result[1];

printf("Header:\n%s\n", output_header);
printf("Content:\n%s\n", output_content);

//second way (doesnt give rnrn)
char *content, *output_header;
size_t size;
FILE *stream;
stream = open_memstream (&content, &size);
char BUF[BUFSIZ];

if((recv(socket_desc, BUF, (BUFSIZ - 1), 0) > 0)
{
    output_header = BUF;
}

while(recv(socket_desc, BUF, (BUFSIZ - 1), 0) > 0)
{
    fprintf (stream, "%s", BUF); //i would just use this as input stream to zlib
}
fflush(stream);
fclose(stream);

printf("Header:\n%s\n", output_header);
printf("Content:\n%s\n", content);

两者给出相同的结果它们打印到终端,但谢胜利,应该打印出一些更多的休息时间,至少我希望,因为他们迷路分割字符串。

Both give the same result printing them to terminal, but the secound one should print out some more breaks, at least i expect, because they get lost splitting the string.

我是新的C,所以我可能只是一些负责简单的东西。

I am new to c, so i might just oversee some easy stuff.

推荐答案

您在呼唤的recv()在一个循环,直到插座断开连接或失败(和写入接收数据流的错误的方式),所有的原始数据存储到你的的char * 缓冲区。即不读的HTTP响应的正确方法,尤其是在使用保持HTTP(在这种情况下,没有断开将发生在反应结束时)。您必须按照 2616 列出的规则。即:

You are calling recv() in a loop until the socket disconnects or fails (and writing the received data to your stream the wrong way), storing all of the raw data into your char* buffer. That is not the correct way to read an HTTP response, especially if HTTP keep-alives are used (in which case no disconnect will occur at the end of the response). You must follow the rules outlined in RFC 2616. Namely:


  1. 阅读,直到\\ r \\ n \\ r \\ n是遇到序列。不要看过去任何更多字节呢。

  1. Read until the "\r\n\r\n" sequence is encountered. Do not read any more bytes past that yet.

分析接收到的报头,每个规则在 RFC 2616第4.4节。他们告诉你剩下的响应数据的实际格式。

Analyze the received headers, per the rules in RFC 2616 Section 4.4. They tell you the actual format of the remaining response data.

阅读每#中发现2格式的数据。

Read the data per the format discovered in #2.

检查接收的头一个连接的presence:关闭头如果响应使用HTTP 1.1,或缺少一个连接:保持活动头如果响应使用HTTP 0.9或1.0。如果检测到,关闭套接字连接的最终因为服务器关闭其结束。否则,保持连接打开并重新将其用于后续的请求(除非你正在使用的连接完成,在这种情况下不关闭它)。

Check the received headers for the presence of a Connection: close header if the response is using HTTP 1.1, or the lack of a Connection: keep-alive header if the response is using HTTP 0.9 or 1.0. If detected, close your end of the socket connection because the server is closing its end. Otherwise, keep the connection open and re-use it for subsequent requests (unless you are done using the connection, in which case do close it).

根据需要处理接收到的数据。

Process the received data as needed.

总之,你需要做更多的东西像这样代替(伪code):

In short, you need to do something more like this instead (pseudo code):

string headers[];
byte data[];

string statusLine = read a CRLF-delimited line;
int statusCode = extract from status line;
string responseVersion = extract from status line;

do
{
    string header = read a CRLF-delimited line;
    if (header == "") break;
    add header to headers list;
}
while (true);

if ( !((statusCode in [1xx, 204, 304]) || (request was "HEAD")) )
{
    if (headers["Transfer-Encoding"] ends with "chunked")
    {
        do
        {
            string chunk = read a CRLF delimited line;
            int chunkSize = extract from chunk line;
            if (chunkSize == 0) break;

            read exactly chunkSize number of bytes into data storage;

            read and discard until a CRLF has been read;
        }
        while (true);

        do
        {
            string header = read a CRLF-delimited line;
            if (header == "") break;
            add header to headers list;
        }
        while (true);
    }
    else if (headers["Content-Length"] is present)
    {
        read exactly Content-Length number of bytes into data storage;
    }
    else if (headers["Content-Type"] == "multipart/byteranges")
    {
        string boundary = extract from Content-Type header;
        read into data storage until terminating boundary has been read;
    }
    else
    {
        read bytes into data storage until disconnected;
    }
}

if (!disconnected)
{
    if (responseVersion == "HTTP/1.1")
    {
        if (headers["Connection"] == "close")
            close connection;
    }
    else
    {
        if (headers["Connection"] != "keep-alive")
            close connection;
    }
}

check statusCode for errors;
process data contents, per info in headers list;

这篇关于头和HTTP服务器响应的内容之间的差异(插座)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆