基本C++;套接字编程 我已经在C++中设置了一个基本的HTTP客户端,到目前为止还可以。这是学校作业,所以还有很多事情要做,但我有个问题

基本C++;套接字编程 我已经在C++中设置了一个基本的HTTP客户端,到目前为止还可以。这是学校作业,所以还有很多事情要做,但我有个问题,c++,c,http,sockets,C++,C,Http,Sockets,我在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: clo

我在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);
}

缓冲区不是null结尾,这是C++中字符串所必需的。当您看到“extra 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);
    }
}

recv
不会向接收到的缓冲区添加
\0
字符串终止符-它只在原始二进制中工作。因此,您的
printf
正在运行
buf
缓冲区的发送(显然最后会查看您的
请求
缓冲区)


buf
的末尾添加nul终止符,或者使用
putchar()
一次打印一个字符的缓冲区(这两种方法都需要存储由
recv()
返回的值)。

recv调用将不为null终止buf;相反,它只会向您提供从导线接收到的原始数据。您需要保存recv的返回值,然后在打印它之前将一个null终止字节添加到buf中。因此,您只能请求sizeof(buf)-1字节。

我怀疑这是因为您的
buf
分配在内存中,就在
请求的下方。在缓冲区上调用
printf
时,
printf
将在找到
NUL
字符(标记字符串结尾)之前尽可能多地打印。如果没有,它将直接进入请求。一般来说,不会有一个,因为
recv
用于接收二进制数据,并且不知道要将其输出作为字符串处理

一个快速修复方法是将接收操作限制为
sizeof(buf)-1
,并使用返回数据的大小自己显式添加
NUL
终止符:

while ((nr = recv(sockfd, buf, sizeof(buf), 0)) > 0)
{
    buf[nr] = 0;
    ...
}
当然,为了(稍微)安全,您需要确保始终收到可打印的数据