我的任务是实现简单的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, "%x\r\n", chunk);
write(sock, tempbuf, strlen(tempbuf));
write(sock, pbuf, chunk);
pbuf += chunk;
strcpy(tempbuf, "\r\n");
write(sock, tempbuf, strlen(tempbuf));
}
if (strlen(pbuf) == 0) {
sprintf(tempbuf, "%x\r\n", 0);
write(sock, tempbuf, strlen(tempbuf));
}
if (strlen(pbuf) > 0) {
sprintf(tempbuf, "%x\r\n", (unsigned)strlen(pbuf));
write(sock, tempbuf, strlen(tempbuf));
write(sock, pbuf, strlen(pbuf));
sprintf(tempbuf, "%x\r\n", 0);
write(sock, tempbuf, strlen(tempbuf));
}
strcpy(tempbuf, "\r\n");
write(sock, tempbuf, strlen(tempbuf));
} while (!feof(html));
fclose(html);
return 0;
}
CHUNK_SIZE
定义为1024,因为我想发送大小为1KB的块。打开页面enter image description here时出现问题
页面显示不正确。
我还设置了Transfer-Encoding:chunked
strcpy(buf, ENCODING);
send(sock, buf, strlen(buf), 0);
ENCODING定义为"传输编码:chunked \ r \ n"
答案 0 :(得分:1)
我想我知道问题出在哪里,但我并不完全确定。
在do
循环中,您会收到buf
个完整数据并发送该数据。然后你得到另一个充满数据的缓冲区并发送它。但是在发送了每个数据缓冲区后,您通过发送0\r\n
终止转移。例如:
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
填充剩余部分),您可能是&# 34;保存"仅在0\r\n
循环之后发送do ... while
,例如:
if (strlen(pbuf) > 0) {
sprintf(tempbuf, "%x\r\n", (unsigned)strlen(pbuf));
write(sock, tempbuf, strlen(tempbuf));
write(sock, pbuf, strlen(pbuf));
//sprintf(tempbuf, "%x\r\n", 0);
//write(sock, tempbuf, strlen(tempbuf));
}
//strcpy(tempbuf, "\r\n");
//write(sock, tempbuf, strlen(tempbuf));
} while (!feof(html));
sprintf(tempbuf, "%x\r\n", 0);
write(sock, tempbuf, strlen(tempbuf));
strcpy(tempbuf, "\r\n");
write(sock, tempbuf, strlen(tempbuf));
另请注意,必须检查fgets
的结果,因为它可以在eof上返回零;缓冲区将不会刷新,您将再次发送最后一部分:
if (fgets(buf, sizeof(buf), html)==NULL) break;
另请参阅有关您不必要地使用tempbuf
的评论。