我已经在C ++中设置了一个基本的HTTP客户端,到目前为止工作正常。这是一个学校作业,所以还有很多工作要做,但我遇到了问题。
我在while循环中使用recv()函数,将响应的各个部分重复添加到我的响应缓冲区,然后每次输出该缓冲区。问题是,在每个响应结束时,HTTP请求也会得到加强。
例如,响应将是页面源代码的一部分,然后是“GET / HTTP / 1.1 ...”,然后是下一个块,然后是“GET ...”,所以上。
这是我的相关代码:
// Prepare request
char request[] = "HEAD /index.html HTTP/1.1\r\nHOST: www.google.com\r\nCONNECTION: close\r\n\r\n";
// Send request
len = send(sockfd, request, sizeof(request), 0);
// Write/output response
while (recv(sockfd, buf, sizeof(buf), 0) != 0)
{
// Read & output response
printf("%s", buf);
}
答案 0 :(得分:7)
缓冲区不是以null结尾,这是C ++中字符串所必需的。当你看到“额外的GET”时,你会看到你不应该的内存,因为stdlib试图打印你的缓冲区,但从未找到'\0'
个字符。
快速解决方法是强制终止缓冲区:
int n = 1;
while (n > 0) {
n = recv(sockfd, buf, sizeof(buf), 0);
if (n > 0) {
// null terminate the buffer so that we can print it
buf[n] = '\0';
// output response
printf("%s", buf);
}
}
答案 1 :(得分:1)
我怀疑是因为您的buf
分配在request
下方的内存中。当您在缓冲区上调用printf
时,printf
会在找到NUL
字符(标记字符串结尾)之前尽可能多地打印。如果没有,它将直接进入请求。通常,不会有一个,因为recv
用于接收二进制数据,并且不知道您想要将其输出视为字符串。
一个快速解决方法是将接收操作限制为sizeof(buf)-1
,并使用返回数据的大小自行显式添加NUL
终止符:
while ((nr = recv(sockfd, buf, sizeof(buf), 0)) > 0)
{
buf[nr] = 0;
...
}
当然,为了(稍微)安全,您需要确保始终可以获得可打印的数据。
答案 2 :(得分:0)
recv
没有向收到的缓冲区添加\0
字符串终止符 - 它只适用于原始二进制文件。因此,printf
正在运行buf
缓冲区的发送(显然最终会查看您的request
缓冲区。)
在buf
的末尾添加一个nul-terminator,或者使用putchar()
一次打印一个字符缓冲区(这两种方法都需要存储{返回的值} {1}})。
答案 3 :(得分:0)
recv调用不会为null-terminate buf;相反,它只会为您提供从电线接收的原始数据。您需要保存recv的返回值,然后在打印之前将自己的空终止字节添加到buf中。因此,您只能要求sizeof(buf)-1个字节。