我使用winsocks来处理我的HTTP请求。在我的服务器端,我运行PHP代码来获取文件的内容,base64&#39,然后打印它(echo)。在我的客户端C ++代码上,我做了一个简单的HTTP get请求。我已经验证问题不在我的服务器端,而是在客户端。
客户端套接字代码:
locale local;
char buffer[1000000];
int i = 0;
string get_Website(string url, string path = "/", string useragent = "Mozilla") {
string website_HTML;
WSADATA wsaData;
SOCKET Socket;
SOCKADDR_IN SockAddr;
int lineCount = 0;
int rowCount = 0;
struct hostent *host;
string get_http;
get_http = "GET " + path + " HTTP/1.0\r\nHost: " + url + "\r\nUser-Agent: " + useragent + "\r\nConnection: close\r\n\r\n";
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
//return 1;-
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
host = gethostbyname(url.c_str());
SockAddr.sin_port = htons(44980);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0) {
cout << "Could not connect";
system("pause");
//return 1;
}
send(Socket, get_http.c_str(), strlen(get_http.c_str()), 0);
int nDataLength;
while ((nDataLength = recv(Socket, buffer, 1000000, 0)) > 0) {
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
website_HTML += buffer[i];
i += 1;
}
}
closesocket(Socket);
WSACleanup();
return website_HTML;
}
尽管我每次都在服务器端返回相同的响应,但响应长度仍在不断变化。大缓冲区的原因是我认为这可能是问题,因为我正在检索整个文件base64编码的形式。
基本上,问题是我没有得到完整/正确的回复。
答案 0 :(得分:0)
while ((nDataLength = recv(Socket, buffer, 1000000, 0)) > 0) {
这是从套接字读取的。读取的字节数进入`nDataLength。紧接着:
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
website_HTML += buffer[i];
i += 1;
}
这个逻辑完全忽略了nDataLength
中的字节数,只是盲目地连续地读取缓冲区的内容,直到第一个控制字符不是换行符或回车符。
除了对您的HTTP请求的响应当然可以包含二进制字符这一事实外,对您的HTTP请求的响应将以多个不同大小的数据包到达,这些数据包将连续写入{{{ 1}}。分配的buffer
似乎在静态存储中,因此它将被初始化为零,并且单个数据包不太可能超过999999字节;所以循环不可能在缓冲区的末尾运行。它会在某个时刻点击buffer
。
但是,由于响应的数据包将具有不同的大小,因此较短的数据包将使其内容替换前一个数据包的初始较长内容;但是破坏的逻辑将无法检测到它,并且会吞下新数据包,然后是前一个数据包的尾端。
有点凌乱。通过使用\0
进行修复,将每个数据包的内容复制并附加到您的字符串中。