C-块的传输编码 - 页面未正确显示



我的任务是实现简单的HTTP服务器。发送响应时,我应该支持块的传输编码。这是我将答复发送给客户的功能。

static int serve_request(int sock, struct conf_arg *arg, char version[])
{
    FILE *html = NULL;
    char buf[MAX_MSG];
    strcat(arg->root, arg->defdoc);
    html = fopen(arg->root, "r");
    if (!html) {
        not_found(sock, version);
        return 0;
    }
    good_responce(sock, version);
    do {
        fgets(buf, sizeof(buf), html);
        const unsigned chunk = CHUNK_SIZE;
        char *pbuf = buf;
        char tempbuf[chunk + 10];
        while (strlen(pbuf) >= chunk) {
            sprintf(tempbuf, "%xrn", chunk);
            write(sock, tempbuf, strlen(tempbuf));
            write(sock, pbuf, chunk);
            pbuf += chunk;
            strcpy(tempbuf, "rn");
            write(sock, tempbuf, strlen(tempbuf));
        }
        if (strlen(pbuf) == 0) {
            sprintf(tempbuf, "%xrn", 0);
            write(sock, tempbuf, strlen(tempbuf));
        }
        if (strlen(pbuf) > 0) {
            sprintf(tempbuf, "%xrn", (unsigned)strlen(pbuf));
            write(sock, tempbuf, strlen(tempbuf));
            write(sock, pbuf, strlen(pbuf));
            sprintf(tempbuf, "%xrn", 0);
            write(sock, tempbuf, strlen(tempbuf));
        }
        strcpy(tempbuf, "rn");
        write(sock, tempbuf, strlen(tempbuf));
    } while (!feof(html));
    fclose(html);
    return 0;
}

CHUNK_SIZE定义为1024,因为我想发送具有1KB大小的块。当我打开页面在此处输入图像描述时,就会发生问题该页面未正确显示。我还设置了转移编码:块

strcpy(buf, ENCODING);
send(sock, buf, strlen(buf), 0);

编码定义为"转移编码:块 r n"

我想我知道问题在哪里,但不完全确定。

在您的do循环中,您获得了一个 buf,其中包含数据,然后发送。然后,您将获得另一个充满数据的缓冲区并发送。但是,在发送了每个数据缓冲区后,您终止通过发送0rn来转移。例如:

1024    // send first chunk
1024    // send second chunk
256     // last part of first bufer
0       // terminate transfer
1024    // send first chunk of second buffer
1024    //...
256
0

虽然最好在发送最后一个块之前再次填充缓冲区(使用memmove将最后一部分向下移动,然后致电fgets以填充其余部分),但是您可以通过仅在之后发送0rn来"保存"。do ... while循环,例如:

        if (strlen(pbuf) > 0) {
            sprintf(tempbuf, "%xrn", (unsigned)strlen(pbuf));
            write(sock, tempbuf, strlen(tempbuf));
            write(sock, pbuf, strlen(pbuf));
            //sprintf(tempbuf, "%xrn", 0);
            //write(sock, tempbuf, strlen(tempbuf));
        }
        //strcpy(tempbuf, "rn");
        //write(sock, tempbuf, strlen(tempbuf));
    } while (!feof(html));
    sprintf(tempbuf, "%xrn", 0);
    write(sock, tempbuf, strlen(tempbuf));
    strcpy(tempbuf, "rn");
    write(sock, tempbuf, strlen(tempbuf));

还请注意,您必须检查fgets的结果,因为它可以在EOF时返回零;缓冲区不会刷新,您将再次发送最后一部分:

    if (fgets(buf, sizeof(buf), html)==NULL) break;

另请参阅有关您不必要使用tempbuf的评论。

最新更新