无法从winsock获取响应的所有字节

时间:2017-07-19 01:35:32

标签: c++ sockets winsock

我使用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编码的形式。

基本上,问题是我没有得到完整/正确的回复。

1 个答案:

答案 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进行修复,将每个数据包的内容复制并附加到您的字符串中。