Search code examples
c++wininet

Counting bytes of file online while reading it


I'm trying to create a basic "Login" system with C++ console. Using PHP to confirm the user information, and C++ will simply retrieve the data the PHP file outputs.

I need the C++ code to read to the end of the file online and stop. The code I'm using counts extra bytes at the end of the file.

int main(){

HINTERNET connect = InternetOpenA("LoginCheckUserAgent 0.0.1v (compatible; harmless;)", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

if (!connect){
    cout << "Connection Failed or Syntax error";
    return 0;
}

HINTERNET OpenAddress = InternetOpenUrlA(connect, "http://localhost/login/check.php?username=admin&password=admin", NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION, 0);

if (!OpenAddress)
{
    DWORD ErrorNum = GetLastError();
    cout << "Failed to open URL \nError No: " << ErrorNum;
    InternetCloseHandle(connect);
    return 0;
}

char DataReceived[4096];
DWORD NumberOfBytesRead = 0;
while (InternetReadFile(OpenAddress, DataReceived, 4096, &NumberOfBytesRead) && NumberOfBytesRead)
{
    cout << DataReceived;
}

InternetCloseHandle(OpenAddress);
InternetCloseHandle(connect);

cin.get();
return 0;

}

Code above gives me: abc123|||||||||||etc.. (Until it hits 4096 bytes) I want it to give me: abc123 I need to read the content of "http://localhost/login/check.php?username=admin&password=admin" exactly with no extra bytes. The code I provided tries reading 4096 bytes.

I know I could just set the 4096 to 1 or something, and only use the PHP to reply with 1 byte. But I want to have the PHP script respond with data that will always be changing so I can't just assume the number of bytes i'm going go be dealing with.

I don't need anyone to fix the code, I just want to know how I can go about determining the bytes I'm going to be reading, and then having my script read it to the end of those bytes. So I don't get unneeded bytes.

Sorry If I made anything confusing.


Solution

  • The number of bytes you've actually read is in NumberOfBytesRead. So, to terminate your string, you just need to write a \0 to that location in your array:

    DataReceived[NumberofBytesRead] = '\0';
    

    So right now, it's making room to read 4096 bytes, but of course only reads as many as were sent. The NumberOfBytesRead tells you how many bytes were actually read, rather than the number you requested.

    Note: depending on the situation, a transmission might be broken up into pieces, so even if data was sent in a single "chunk", it might be received in several consecutive read attempts.

    Typically you want to prefix your data with its length, so you can read (say) a 4-byte header telling you the length of the remainder, and know to keep reading until you've received the whole thing (or give up, such as if it's taking too long).