C解析HTTP分块传输编码响应。

4

我正在开发一个客户端,需要解析分块类型的HTTP传输。我一直在努力解决以下问题,但是无法成功,希望有人能够更快地捕捉到我的错误。总结一下问题:似乎客户端没有接收到所有的块,因此导致了后续过程的混乱。提前感谢!

 while(cflag){
    pfile_chunk = malloc(CHUNK_SIZE+1);
    memset(pfile_chunk, 0, CHUNK_SIZE);
    cPtr = pfile_chunk;
    cPtr2 = NULL;
    k=0;
    while(*(cPtr-1) != '\n'){
        k++;
        recv(sock, cPtr, 1, 0);
        cPtr = pfile_chunk+k;
    }
    cPtr2 = strchr(pfile_chunk, '\r');
    *cPtr2 = '\0';
    sscanf(pfile_chunk, "%x", &l);
    if(l == 0)
        break;
    printf("\nServer wants to deliver %ld bytes.\n", l);
    pfile_chunk = realloc(pfile_chunk, l+1);
    memset(pfile_chunk, 0, l);
    recv(sock, pfile_chunk, l, 0);
    fputs(pfile_chunk, f);
    printf("GOT THIS, SIZE %ld:\n%s\n", strlen(pfile_chunk), pfile_chunk);
    //get next \r\n bytes.
    recv(sock, NULL, 2, 0);
}

提前道歉,我的代码有些凌乱,这主要是因为我尝试了很多不同的方法。 - E Klonowski
你介意发布你的最终整理好的代码吗?我也在处理这个任务时遇到了困难。不确定如何将从缓冲区读取的内容与实际的HTTP块进行调和。你是在解析块之前存储整个HTTP响应吗? - CFL_Jeff
2个回答

5

至少,您应该检查recv的返回值,以查看您是否获得了预期获得的字节数。

在网络上进行短读取肯定是可能的,因为系统调用将返回在您发出调用时套接字接收缓冲区中可用的任何内容。

实现一个循环,直到读取完整个块,或者在最后一个参数中传递MSG_WAITALL标志给recv。但是,您仍然需要检查recv的错误。

ssize_t r = recv(sock, pfile_chunk, l, MSG_WAITALL);
if (r < l) {
    /* check for errors ... */
} else {
    /* got the data */
}

谢谢您,先生。我甚至没有考虑到send/recv标志。由于我匆忙地移动了松散的代码,所以错误检查并不存在。非常感谢!有人给这个人点赞吧,我没有足够的声望。 - E Klonowski

2
看起来你在 while 循环的第一次解引用操作访问到了数组开始之前的位置,这可能不是期望的行为。希望那个内存位置通常不会包含 \n,否则会破坏你的 read 操作。我预计那个位置可能包含一些关于你的 malloc 的信息,但不太可能是 \n,所以你可能从来没有遇到过这个问题。
另外,希望你可以相信 socket 的另一端在发送超过 CHUNK_SIZE+1 之前会给你发送一个 \n。否则,程序可能会崩溃。通常情况下,我预计发送方只会发送10个或更少ASCII数字字符和一个CRLF作为块头,但他们理论上也可以发送一堆长的扩展块头字段。
除此之外,还有一个由 user315052 发现的更重要的问题,你应该告诉 recv 方法等待你请求的所有数据,或者检查它实际读取了多少数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接