无法接收 HTTP 响应 body C++
Unable to receive HTTP response body C++
首先,这是我用来发出 HTTP POST 请求的 C++ 代码。它链接到 ws2_32.lib
.
int POST_TEST(std::string URL, std::string DATA)
{
//**************************************************
std::string TEXT = "";
std::string DIRECTORY = URL.substr(URL.find(".com") + std::string(".com").length());
std::string HOST = URL.substr(0, URL.find(".com", std::string(".com").length())) + ".com";
std::string REQ = "POST " + DIRECTORY + " HTTP/1.1\r\nContent-Length: " + to_string(DATA.length()) + "\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nHost: " + HOST + "\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:44.0) Gecko/20100101 Firefox/44.0\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n" + DATA;
const char * REQUEST = REQ.c_str();
//**************************************************
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 1;
SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *host = gethostbyname(HOST.c_str());
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if(connect(Socket,(SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0)
return 1;
send(Socket, REQUEST, strlen(REQUEST), 0);
char buffer[1000];
int nDataLength;
while((nDataLength = recv(Socket, buffer, 1000, 0)) > 0)
{
int i = 0;
while(buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r')
{
TEXT += buffer[i];
i++;
}
}
closesocket(Socket);
WSACleanup();
MessageBoxA(NULL, TEXT.c_str(), "HTTP Response", MB_OK);
return 0;
}
POST_TEST("blah.com/a.php", "a=blah");
代码运行良好,但我只收到 HTTP Header 响应,我没有看到响应 BODY。使用 Python 向同一个 php 页面发出 POST 请求使我能够很好地看到响应 body。我不确定我是否误解了什么,或者我的代码有错误。
我 POST 访问的 PHP 页面位于我自己的服务器上。 PHP 回显了一些文本,但我没有在响应中看到它。这是我得到的回复:
HTTP/1.1 200 OK
Server: nginx/1.8.1
Date: Fri, 08 Apr 2016 02:10:14 GMT
Content-Type: text/html
Content-Length: 286
Connection: keep-alive
Vary: Accept-Encoding
Content-Encoding: gzip
我怎样才能看到完整的回复?
显示的代码中有两个错误。
它不检查 send()
中的 return 值。 send()
不保证实际发送了请求发送的字节数。来自 send()
的 return 值可能 return 表示写入的字节数少于请求的字节数。您有责任进行检查,然后再次尝试 send()
剩余字节。
读取和收集响应的逻辑错误。 recv()
告诉您收到了多少字节。这完全被忽略了。相反,代码会扫描读取缓冲区,直到将控制字符视为一个字节。
请注意,您的 HTTP 响应表明您正在获取原始的、gzip 压缩的二进制数据。在实际响应的前几个字节中,很可能会有一些二进制字节对应于 ASCII 控制字符的值。你的循环会在那个时候戛然而止。
即使您期望的是纯文本响应,这种逻辑仍然是错误的。 recv()
中的 return 值告诉您收到了多少字节,仅此而已。
首先,这是我用来发出 HTTP POST 请求的 C++ 代码。它链接到 ws2_32.lib
.
int POST_TEST(std::string URL, std::string DATA)
{
//**************************************************
std::string TEXT = "";
std::string DIRECTORY = URL.substr(URL.find(".com") + std::string(".com").length());
std::string HOST = URL.substr(0, URL.find(".com", std::string(".com").length())) + ".com";
std::string REQ = "POST " + DIRECTORY + " HTTP/1.1\r\nContent-Length: " + to_string(DATA.length()) + "\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nHost: " + HOST + "\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:44.0) Gecko/20100101 Firefox/44.0\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n" + DATA;
const char * REQUEST = REQ.c_str();
//**************************************************
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 1;
SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *host = gethostbyname(HOST.c_str());
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if(connect(Socket,(SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0)
return 1;
send(Socket, REQUEST, strlen(REQUEST), 0);
char buffer[1000];
int nDataLength;
while((nDataLength = recv(Socket, buffer, 1000, 0)) > 0)
{
int i = 0;
while(buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r')
{
TEXT += buffer[i];
i++;
}
}
closesocket(Socket);
WSACleanup();
MessageBoxA(NULL, TEXT.c_str(), "HTTP Response", MB_OK);
return 0;
}
POST_TEST("blah.com/a.php", "a=blah");
代码运行良好,但我只收到 HTTP Header 响应,我没有看到响应 BODY。使用 Python 向同一个 php 页面发出 POST 请求使我能够很好地看到响应 body。我不确定我是否误解了什么,或者我的代码有错误。
我 POST 访问的 PHP 页面位于我自己的服务器上。 PHP 回显了一些文本,但我没有在响应中看到它。这是我得到的回复:
HTTP/1.1 200 OK
Server: nginx/1.8.1
Date: Fri, 08 Apr 2016 02:10:14 GMT
Content-Type: text/html
Content-Length: 286
Connection: keep-alive
Vary: Accept-Encoding
Content-Encoding: gzip
我怎样才能看到完整的回复?
显示的代码中有两个错误。
它不检查
send()
中的 return 值。send()
不保证实际发送了请求发送的字节数。来自send()
的 return 值可能 return 表示写入的字节数少于请求的字节数。您有责任进行检查,然后再次尝试send()
剩余字节。读取和收集响应的逻辑错误。
recv()
告诉您收到了多少字节。这完全被忽略了。相反,代码会扫描读取缓冲区,直到将控制字符视为一个字节。
请注意,您的 HTTP 响应表明您正在获取原始的、gzip 压缩的二进制数据。在实际响应的前几个字节中,很可能会有一些二进制字节对应于 ASCII 控制字符的值。你的循环会在那个时候戛然而止。
即使您期望的是纯文本响应,这种逻辑仍然是错误的。 recv()
中的 return 值告诉您收到了多少字节,仅此而已。